home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
LSD Docs
/
LSD Docs.iso
/
FILEZ
/
lsd34.dms
/
lsd34.adf
/
AREXX.doc2.pp
/
AREXX.doc2
Wrap
Text File
|
1990-09-13
|
156KB
|
3,499 lines
AREXX USER'S REFERENCE MANUAL
PART 2
CHAPTER 7 TRACING AND INTERRUPTS
ARexx provides tracing and source-level debugging facilities that are unusual
in a high-level language. Tracing refers to the ability to display selected
statements in a program as the program executes. When a clause is traced,its
line number,source text,and related information are displayed on the console.
The tracing action of the interpreter is determined by a trace option that
selects which source clauses will be traced,and two modifier flags that control
command inhibition and interactive tracing.
The internal interrupt system enables an ARexx program to detect certain
synchronous or asynchronous events and to take special actions when they occur.
Events such as a syntax error or an external halt request that would normally
cause the program to exit can instead be trapped so that corrective actions can
be taken.
7-1 TRACING OPTIONS
Trace options are sometimes called an alphabetic options,since the keywords
that select an option can be shortened to one letter for convenience. The
alphabetic options are:
ALL. All clauses are traced.
COMMANDS. All command clauses are traced before being sent to the external
host. Non-zero return codes are displayed on the console.
ERRORS. Commands that generate a non-zero return code are traced after the
clause is executed.
INTERMEDIATES. All clauses are traced,and intermediate results are displayed
during expression evaluation. These include the values retrieved for variables,
expanded compound names,and the results of function calls.
LABELS. All label clauses are traced as they are executed. A label will be
displayed each time a transfer of control takes place.
NORMAL. Command clauses will return codes that exceed the current error failure
level are traced after execution,and an error message is displayed. This is the
default trace option.
RESULTS. All clauses are traced before execution,and the final result of each
expression is displayed. Values assigned to variables by ARG,PARSE,or PULL
instructions are also displayed.
SCAN. This is a special option that traces all clauses and checks for errors,
but suppresses the actual execution of the statements. It is helpful as a
preliminary screening steop for a newly-created program.
The tracing mode can be set using either the TRACE instruction or the TRACE()
Built-In function. The RESULTS trace option is recommended for general-purpose
testing. Tracing can be selectively disabled from within a program so that
previously-tested parts of a program can be skipped.
71
7-2 DISPLAY FORMATTING
Each trace line displayed on the console is indented to show the effective
control(nesting)level at that clause,and is identified by a special three-
character code,as shown in Table 7.1 below. The source for each clause is
preceded by its line number in the program. Expression results or intermediates
are enclosed in double quotes so that leading and trailing blanks will be
apparent.
TABLE 7.1 TRACING PREFIX CODES
CODE DISPLAYED VALUES
+++ Command or syntax error
>C> Expanded compound name
>F> Result of a function call
>L> Label clause
>O> Result of a dyadic operation
>P> Result of a prefix operation
>U> Uninitialized variable
>V> Value of a variable
>>> Expression or template result
>.> "Placeholder" token value
TRACING OUTPUT
The tracing output from a program is always directed to one of two logical
streams. The interpreter first checks for a stream named STDERR,and directs the
output there if the steam exists. Otherwise the trace output goes to the
standard output stream STDOUT and will be interleaved with the normal console
output of the program. The STDERR and STDOUT streams can be opened and closed
under program control,so the programmer has complete control over the
destination of tracing output.
In some cases a program may not have a predefined output stream. For example,a
program invoked from a host application that did not provide input and output
streams would not have an output console. To provide a tracing facility for
such programs,the resident process can open a special global tracing console
for use by any active program. When this console opens,the interpreter
automatically opens a stream named STDERR for each ARexx program in which
STDERR is not currently defined,and the program then diverts its tracing output
to the new stream.
The global console can be opened and closed using the command utilities too and
tcc,respectively. The console may not close immediately upon request,however.
The resident process waits until all active programs have diverted their
tracing streams back to the default state before actually closing the console.
Applications programs may provide direct control over the tracing console by
sending request packets to the resident process,which is discussed in Chapter
10.
The trace stream(STDERR or STDOUT)is also used for trace input,so a program in
interactive tracing mode will wait for user input from this console. The global
tracing console is always shared among all currently active programs. Since it
may be confusing to have several programs simultaneously writing to the same
console,it is recommended that only one program at a time be traced using the
global console.
72
COMMAND INHIBITION
ARexx provides a tracing mode called command inhibition that suppresses host
commands. In this mode command clauses are evaluated in the normal manner,but
the command is not actually sent to the external host,and the return code is
set to zero. This provides a way to test programs that issue potentially
destructive commands,such as erasing files or formatting disks. Command
inhibition does not apply to command clauses that are entered interactively.
These commands are always performed,but the value of the special variable RC is
left unchanged.
Command inhibition may be used in conjunction with any trace option. It is
controlled by the "!" character,which may appear by itself or may precede any
of the alphabetic options in a TRACE instruction. Each occurrence of the "!"
character "toggles" the inhibition mode currently in effect. Command inhibition
is cleared when tracing is set to OFF.
7-3 INTERACTIVE TRACING
Interactive tracing is a debugging facility that allows the user to enter
source statements while a program is executing. These statements may be used to
examine or modify variable values,issue commands,or otherwise interact with the
program. Any valid language statements can be entered interactively,with the
same rules and restrictions that apply to the INTERPRET instruction. In
particular,compound statements such as DO and SELECT must be complete within
the entered line.
Interactive tracing can be used with any of the trace options. While in
interactive tracing mode,the interpreter pauses after each traced clause and
prompts for input with the code "+++." At each pause,three types of user
responses are possible.
If a null line is entered,the program continues to the next pause
point.
If an "=" character is entered,the preceding clause is executed again.
Any other input is treated as a debugging statement,and is scanned and
executed.
The pause points during interactive tracing are determined by the tracing
option currently in effect,as the interpreter pauses only after a traced
clause. However,certain instructions cannot be safely(or sensibly)re-executed,
so the interpreter will not pause after executing one of these. The "no-pause"
instructions are CALL,DO,ELSE,IF,THEN,and OTHERWISE. The interpreter will also
not pause after any clause that generate and execution error.
Interactive tracing mode is controlled by the "?" character,either by itself or
in combination with an alphabetic trace option. Any number of "?" characters
may precede an option,and each occurrence toggles the mode currently in effect.
For example,if the current trace option was NORMAL,then "TRACE ?R" would set
the option to RESULTS and select interactive tracing mode. A subsequent "TRACE
?" would turn off interactive tracing.
73
ERROR PROCESSING
The ARexx interpreter provides special error processing while it executes
debugging statements. Errors that occur during interactive debugging are
reported,but do not cause the program to terminate. This special processing
applies only to the statements that were entered interactively. Errors occuring
in the program source statements are treated in the usual way whether or not
the interpreter is in interactive tracing mode.
In addition to the special error processing,the interpreter also disables the
internal interrupt flags during interactive debugging. This is necessary to
prevent an accidental transfer of control due to an error or uninitialized
variable. However,if a "SIGNAL label" instruction is entered,the transfer will
take place,and any remaining interactive input will be abandoned. The SIGNAL
instruction can still be used to alter the interrupt flags,and the new settings
will take effect when the interpreter returns to normal processing.
THE EXTERNAL TRACING FLAG
The ARexx resident process maintains an external tracing flag that can be used
to force programs into interactive tracing mode. The tracing flag can be set
using the ts command utility. When the flag is set,any program not already in
interactive tracing mode will enter it immediately. The internal trace option
is set to RESULTS unless it is currently set to INTERMEDIATES or SCAN,in which
case it remains unchanged. Programs invoked while the external tracing flag is
set will begin executing in interactive tracing mode.
The external tracing flag provides a way to regain control over programs that
are caught in loops or are otherwise unresponsive. Once a program enters
interactive tracing mode,the user can step through the program statements and
diagnose the problem. There is one caveat,though:external tracing is global
flag,so all currently-active programs are affected by it. The tracing flag
remains set until it is cleared using the "te" command utility. Each program
maintains an internal copy of the last state of the tracing flag,and sets its
tracing option to OFF when it observes that the tracing flag has been cleared.
7-4 INTERRUPTS
ARexx maintains an internal interrupt system that can be used to detect and
trap certain error conditions. When an interrupt is enabled and its
corresponding condition arises,a transfer of control to the label specific to
that interrupt occurs. This allows a program to retain control in circumstances
that might otherwise cause the program to terminate. The interrupt conditions
can caused by either synchronous events like a syntax error,or asynchronous
events like a "control-C" break request. Note that these internal interrupts
are completely separate from the hardware interrupt system managed by the EXEC
operating system.
The interrupts supported by ARexx are described below. The name assigned to
each is actually the label to which control will be tranferred. Thus,a SYNTAX
interrupt will transfer control to the label "SYNTAX:." Interrupts can be
enabled or disabled using the SIGNAL instruction. For example,the instruction
"SIGNAL ON SYNTAX" would enable the SYNTAX interrupt.
74
BREAK_C. This interrupt will trap a control-C break request generated by DOS.
If the interrupt is not enabled,the program terminates immediately with the
error message "Execution halted" and returns with the error code set to 2.
BREAK_D. The interrupt will detect and trap a control-D break request issued by
DOS. The break request is ignored if the interrupt is not enabled.
BREAK_E. The interrupt will detect and trap a control-E break request issued by
DOS. The break request is ignored if the interrupt is not enabled.
BREAK_F. The interrupt will detect and trap a control-F break request issued by
DOS. The break request is ignored if the interrupt is not enabled.
ERROR. This interrupt is generated by any host command that returns a non-zero
code.
HALT. An external halt request will be trapped if this interrupt is enabled.
Otherwise,the program terminates immediately with the error message "Execution
halted" and returns with the error code set to 2.
IOERR. Errors detected by the I/O system will be trapped if this interrupt is
enabled.
NOVALUE. An interrupt will occur if an uninitialized variable is used while
this condition is enabled. The usage could be within an expression,in the UPPER
instruction,or with the VALUE()built-in function.
SYNTAX. A syntax or execution error will generate this interrupt. Not all
errors such errors can be trapped,however. In particular,certain errors
occurring before a program is actually executing,and those detected by the
ARexx external interface,cannot be trapped by the SYNTAX interrupt.
When an interrupt forces a transfer of control,all of the currently active
control ranges are dismantled,and the interrupt that caused the transfer is
disabled. This latter action is necessary to prevent a possible recursive
interrupt loop. Only the control structures in the current environment are
affected,so an interrupt generated within a function will not affect the
caller's environment.
SPECIAL VARIABLES. Two special variables are affected when an interrupt occurs.
The variable SIGL is always set to the current line number before the transfer
of control takes place,so that the program can determine which source line was
being executed. When an ERROR or SYNTAX interrupt occurs,the variable RC is set
to the error code that caused the condition. For ERROR interrupts this value
will be a command return code,and can usually be interpreted as an error
severity level. The value for SYNTAX interrupts is always an ARexx error code.
Interrupts are useful primarily to allow a program to take special
error-recovery actions. Such actions might involve informing external programs
that an error ocurred,or simply reporting further diagnostics to help in
isolating the problem. In the following example,the program issues a "message"
command to an external host called "MyEdit" whenever a syntax error is
detected:
75
/* A macro program for 'MyEdit' */
signal on syntax /* enable interrupt */
.
. (normal processing)
.
exit
syntax: /* syntax error detected*/
address 'MyEdit'
'message' 'error' rc errortext(rc)
exit 10
76
CHAPTER 8 PARSING AND TEMPLATES
Parsing is a operation that extracts substrings from a string and assigns them
to variables. It corresponds roughly to the notion of a "formatted read" used
in other languages,but has been generalized in the several ways. Parsing is
performed using the PARSE instruction or its variants ARG and PULL. The input
for the operation is called the parse string and can come from several sources;
these source options are described with the PARSE instruction in Chapter 4.
Parsing is controlled by a template,a group of tokens that specifies both the
variables to be given values and the way to determine the value strings.
Templates were described briefly with the PARSE instruction;the present chapter
presents a more formal description of their structure and operation.
8-1 TEMPLATE STRUCTURE
The tokens that are valid in a template are symbols,strings,operators,
parentheses,and commas. Any blanks that may be present as separators are
removed before the template is processed. The tokens in a template ultimately
serve to specify one of the two basic template objects:
Markers determine a scan position within the parse string,and
Targets are symbols to be assigned a value.
With these objects in mind,the parsing process can be described as one of
associating with each target a starting and ending position in the parse
string. The substring between these positions then becomes the value for the
target.
MARKETS. There are three types of marker objects:
ABSOLUTE markers specify an actual index position in the parse string,
RELATIVE markers specify a positive or negative offset from the current
position,and
PATTERN markers specify a position implicitly,by matching the pattern against
the parse string beginning at the current scan position.
TARGETS. Targets,like markers,can affect the scan position if value strings are
being extracted by tokenization. Parsing by tokenization extracts words(tokens)
from the parse string, and is used whenever a target is followed immediately
77
by another target. During tokenization the current scan position is advanced
past any blanks to the start of the next word. The ending index is the position
just past the end of the word,so that the value string has neither leading nor
trailing blanks.
TEMPLATE OBJECTS
Each template object is specified by one or more tokens,which have the
following interpretations.
SYMBOLS. A symbol token may specify either a target or a marker object. If it
follows an operator token(+,-,or=),it represents a marker,and the symbol value
is used as an absolute or relative position. Symbols enclosed in parentheses
specify pattern markers,and the symbol value is used as the pattern string.
If neither of the preceding cases applies and the symbol is a variable,then it
specifies a target. Fixed symbols always specify absolute markers and must be
whole numbers,except for the period(.)symbol which defines a placeholder
target.
STRINGS. A string token always represents a pattern marker.
PARENTHESES. A symbol enclosed in parentheses is a pattern marker,and the value
of the symbol is used as the pattern string. While the symbol may be either
fixed or variable,it will usually be a variable,since a fixed pattern could be
given more simply as a string.
OPERATORS. The three operators "+,"-,"and "=" are valid within a template,and
must be followed by a fixed or variable symbol. The value of the symbol is used
as a marker and must therefore represent a whole number. The "+" and "-"
operators signify a relative marker,whose value is negated by the "-" operator.
The "=" operator indicates an absolute marker,and is optional if the marker is
defined by a fixed symbol.
COMMAS. The comma(,)marks the end of a template,and is used as a separator when
multiple templates are provided with an instruction. The interpreter obtains a
new parse string before processing each succeeding template. For some source
options,the new string will be identical to the previous one. The ARG,EXTERNAL,
and PULL options will generally supply a different string,as will the VAR
option if the variable has been modified.
THE SCANNING PROCESS
Scan positions are expressed as an index in the parse string,and can range from
1(the start of the string)to the length of the string plus 1(the end). An
attempt to set the scan position before the start or after the end of the
string instead sets it to the beginning or end,respectively.
The substring specified by two scan indices includes the characters from the
starting position up to,but not including,the ending position. For example,the
indices 1 and 10 specify characters 1-9 in the parse string. One additional
rule is applied if the second scan index is less than or equal to the first: in
this case the remainder of the parse string is used as the substring. This
means that a template specificaiton like
78
parse arg 1 all 1 first second
will assign the entire parse string to the variable ALL. Of course,if the
current scan index is already at the end of the parse string,then the remainder
is just the null string.
When a pattern marker is matched against the parse string,the marker position
is the index of the first character of the matched pattern,or the end of the
string if no match was found. The pattern is removed from the string whenever a
match is found. This is the only operation that modifies the parse string
during the parsing process.
Templates are scanned from left to right with the initial scan index set to 1,
the start of the parse string. The scan position is updated each time a marker
object is encountered,according to the type and value of the marker. Whenever a
target object is found,the value to be assigned is determined by examining the
next template object. If the next object is another target,the value string is
determined by tokenizing the parse string. Otherwise,the current scan position
is used as the start of the value string,and the position specified by the
following marker is used as the end point.
The scan continous until all of the objects in the template have been used.
Note that every target will be assigned a value;once the parse string has been
exhausted,the null string is assigned to any remaining targets.
8-2 TEMPLATES IN ACTION
The preceding section is rather abstract,so let's look now at some examples of
parsing with templates.
PARSING BY TOKENIZATION
Computer programs frequently require splitting a string into its component
words or tokens. This is easily accomplished with a template consisting
entirely of variables(targets).
/* Assume "hammer 1 each $600.00" was entered */
pull item qty untils cost .
In this example the input line from the PULL instruction is split into words
and assigned to the variables in the template. The variable item receives the
value "hammer," qty is set to "1," units is set to "each," and cost gets the
value "$600.00." The final placeholder(.) is given a null value,since there are
only four words in the input. However,it forces the preceding variable cost to
be given a tokenized value. If the placeholder were omitted,the remainder of
the parse string would be assigned to cost,which would then have a leading
blank.
In the next example,the first word of a string is removed and the remainder is
placed back in the string. The process continues until no more words are
extracted.
79
/* Assume "result" contains a string of words */
do forever
/* Get first word of string */
parse var result first result
if first == '' then leave
/* ... process words ... */
end
PATTERN PARSING
The next example uses pattern markers to extract the desired fields. The
"pattern" in this case is very simple -- just a single character -- but in
general can be an arbitrary string of any length. This form of parsing is
useful whenever delimiter characters are present in the parse string.
/* Assume an argument string "12,34.5,1 */
arg hours ',' rate ',' withhold
Keep in mind that the pattern is actually removed from the parse string when a
match is found. If the parse string is scanned again from the beginning,the
length and structure of the string may be different than at the start of the
parsing process. However,the original source of the string is never modified.
POSITIONAL MARKERS
Parsing with positional markers is used whenever the fields of interest are
known to be in certain positions in a string. In the next example,the records
being processed contain a variable length field. The starting position and
length of the field are given in the first part of the record,and a variable
positional marker is used to extact the desired field.
/* records look like: */
/* start: 1-5 */
/* length: 6-10 */
/* name: @(start,length) */
parse value record with 1 start +5 length +5 =start name +length
The "=start" sequence in the above example is an absolute marker whose value is
the position paced in the variable start earlier in the scan. The "+length"
sequence supplies the effective length of the field.
MULTIPLE TEMPLATES
It is sometimes useful to specify more than one template with an instruction,
which can be done by separating the templates with a comma. In this next
example,the ARG instruction(or PARSE UPPER ARG)is used to access the argument
strings provided when the program was called. Each template accesses the
succeeding argument string.
80
/* Assume arguments were ('one two',12,sort) */
arg first second,amount,action,option
The first template consists of the variables first and second,which are set to
the values "one" and "two,"respectively. In the next two templates amount gets
the value "12" and action is set to "SORT". The last template consists of the
variable "option,"which is set to the null string,since only three arguments
were available.
When multiple templates are used with the EXTERNAL or PULL source options,each
additional template requests an additional line of input from the user. In the
next example two lines of input are read:
/* read last,first,and middle names and ssn */
pull last ',' first middle,ssn
The first input line is expected to have three words,the first of which is
followed by a comma,which are assigned to the variables last,first,and middle.
The entire second input line is assigned to the variable ssn.
Multiple templates can be useful even with a source option that returns the
identical parse string. If the first template included pattern markers that
altered the parse string,the subsequent templates could still access the
original string. Note that subsequent parse strings obtained from the VALUE
source do not cause the expression to be reevaluated,but only retrieve the
prior result.
81
CHAPTER 9 THE RESIDENT PROCESS
This chapter describes some of the capabilities of the ARexx resident process,
a global communications and resources manager. The material presented here is
directed to the general user;Chapter 10 covers these topics in greater depth
for software developers who wish to integrate ARexx with other applications
programs.
The resident process must be active before any ARexx programs can be run. It
announces its presence to the system by opening a public message port named
"REXX,"so applications programs that use ARexx should check for the presence of
this port. If the port is not open,the user can either be informed that the
macro processor is not available,or else the applications program can start up
the resident process. The latter option can be done using the rexxmast command.
The primary function of the resident process is to launch ARexx programs. When
an applications program sends a "command" or "function" message to the "REXX"
port,the resident process creates a new DOS process to execute the program, and
forwards the invocation message to newly created process. It also creates a new
instance of the ARexx global data structure,which links together all of the
structures manipulated by the program.
In addition to launching programs,the resident process managers various
resources used by ARexx. These resources include a list of available function
libraries called the Library List,a list of(name,value)pairs called the Clip
List,and a list of the currently active ARexx programs. Built-In functions are
available to manipulate the Library List and Clip List from within an ARexx
program. Applications programs can modify a resource list either by sending a
request packet to the resident process or by direct manipulation of the list.
9-1 COMMAND UTILITIES
ARexx is supplied with a number of command utilities to provide various control
functions. These are executable modules that can be run from the CLI,and should
reside in the system command(C:)directory for convenience. These commands are
relevant only when the ARexx resident process is active.
The functions performed by these utilities may also be available from within an
applications program. All of the utilities are implemented by sending message
packets to the resident process,so an application designed to work closely with
ARexx could easily provide these functions as part of its control menu.
HI
Usage:HI
Sets the global halt flag,which causes all active programs to receive an
external halt request. Each program will exit immediately unless its HALT
interrupt has been enabled. The halt flag does not remain set,but is cleared
automatically after all current programs have received the request.
83
RX
Usage:RX name[arguments]
This command launches an ARexx program. If the specified name includes an
explicit path,only that directory is searched for the program;otherwise,the
current directory and the system REXX: device are checked for a program with
the given name. The optional argument string is passed to the program.
RXSET
Usage:RXSET name value
Adds a(name,value)pair to the Clip List. Name strings are assumed to be in
mixed case. If a pair with the same name already exists,its value is replaced
with the current string. If a name without a value string is given,the entry is
removed from the Clip List.
RXC
Usage:RXC
Closes the resident process. The "REXX" public port is withdrawn immediately,
and the resident process exits as soon as the last ARexx program finishes. No
new programs can be launched after a "close" request.
TCC
Usage:TCC
Closes the global tracing console as soon as all active programs are no longer
using it. All read read requests queued to the console must be satisfied before
it can be closed.
TCO
Usage:TCO
Open the global tracing console. The tracing output from all active programs is
diverted automatically to the new console. The console window can be moved and
resized by the user,and can be closed with the "TCC" command.
TE
Usage:TE
Clears the global tracing flag,which forces the tracing mode to OFF for all
active ARexx programs.
TS
Usage:TS
Starts interactive tracing by setting the external trace flag,which forces all
active ARexx programs into interactive tracing mode. Programs will start
producing trace output and will pause after the next statement. This command is
useful for regaining control over programs caught in infinite loops or
otherwise misbehaving. The trace flag remains set until cleared by the TE
command,so subsequent program invocations will begin executing in interactive
tracing mode.
84
9-2 RESOURCE MANAGEMENT
Individual ARexx programs manage their internal memory allocation and I/O file
resources,but some resources need to be available to all programs. The
management of these global resources is one of the major functions of the
resident process. Global resources are maintained as doubly-linked lists,in
keeping with the general design principles of the EXEC operating system. Linked
lists provide a flexible and open mechanism for resource management,and help
avoid the built-in limits common with other approaches.
THE GLOBAL TRACING CONSOLE
The tracing output from an ARexx program usually goes to the standard output
stream STDOUT,and is therefore interleaved with the normal output of the
program. Since this may be confusing at times,a global trace console can be
opened to display only tracing output. The console can be opened using the tco
command utility or be sending an RXTCOPN request packet to the resident
process. ARexx programs will automatically divert their tracing output to the
new window,which is opened as a standard AmigaDOS console. The user can move it
and resize it as required.
The tracing console also serves as the input stream for programs during
interactive tracing. When a program pauses for tracing input,the input line
must be entered at the trace console. Any number of programs may use the
tracing console simultaneously,although it is generally recommended that only
one program at a time be traced.
The tracing console can be closed using the tcc command or by sending an
RXTCCLS request packet to the resident process. The closing is delayed until
all read requests to the console have been satisfied. Only when all of the
active programs indicate that they are no longer using the console will it
actually be closed.
THE LIBRARY LIST
The resident process maintains a Library List of the function libraries and
function hosts currently available to ARexx programs. This list is used to
resolve all references to external functions. Each entry has an associated
search priority in the range 100 to -100,with the higher-valued entries being
searched first until the requested function is found. The list is searched by
calling each entry,using the appropriate protocol,until the return code
indicates that the function was found.
The two types of entities maintained by the list are quite different in some
respects,but the ultimate way in which a function call is resolved is
transparent to the calling program. A function library is a collection of
functions organized as an Amiga shared library,while a function host is a
separate task that manages a message port. Function libraries are called as
part of the ARexx interpreter's task context,but calls to function hosts are
mediated by passing a message packet. The ARexx resident process is itself a
function host,and is installed in the Library List at a priority of -60.
The resident process provides addition and deletion operations for maintaining
the Library List;these operations are performed by sending an appropriate
message packet. The Library List is always maintained in priority order. Within
a given priority level any new entries are added to the end of the chain, so
that entries added first will be searched fist. The priority levels are
85
significant if any of the libraries have duplicate function name
definitions,since the function located further down the search chain could
never be called.
FUNCTION LIBRARIES. Each function library entry in the Library List contains a
library name,a search priority,an entry point offset,and a version number. The
library name must refer to a standard Amiga shared library residing in the
system LIBS: directory so that it can be loaded when needed. Function libraries
can be created and maintained by users or applications developers;Chapter 10
has information on their design and implementation.
The "query" function is the library entry point that is actually called by the
interpreter. It must be specified as an integer offset(e.g. "-30")from the
library base. The return code from the query call then indicates whether the
desired function was found;it it was,the function is called with the parameters
passed by the interpreter and the function result is returned to the caller.
Otherwise,the search continues with the next entry in the list. In either event
the library is closed to await the next call.
A note of caution: not every Amiga shared library can be used as a function
library. Function libraries must have a special entry point to perform the
dynamic linking required to access the functions from within ARexx. Each
library should include documentation providing its version number and the
integer offset to its "query" entry point.
FUNCITON HOSTS. The name associated with a function host is the name of its
public message port. Function calls are passed to the host as a message packet;
it is then up to the individual host to determine whether the specified
function name is one that it recognizes. The name resolution is completely
internal to the host,so function hosts provide a natural gateway mechanism for
implementing remote procedure calls to other machines in a network.
THE CLIP LIST
The Clip List maintains a set of(name,value)pairs that may be used for a
variety of purposes. Each entry in the list consists of a name and a value
string,and may be located by name. Since the Clip List is publicly accessible,
it may be used as a general clipboard-like mechanism for intertask
communication. In general,the names used should be chosen to be unique to an
application to prevent collisions with other programs. Any number of entries
may be posted to the list.
One potential application for the Clip List is as a mechanism for loading
predefined constants into an ARexx program. The language definition does not
include a facility comparable to the "header file" preprocessor in the "C"
language. However,consider a string in the Clip List of the form
pi=3.14159; e=2.718; sqrt2=1.414 ...
i.e.,a series of assignments separated by semicolons. In use,such a string
could be retrieved by name using the Built-In function GETCLIP()and then
INTERPRETed within the program. The assignment statements within the string
would then create the required constant definitions. The following program
fragment illustrates the process::
86
/* assume a string called "numbers" is available*/
numbers=getclip('numbers') /* case-sensitive */
interpret numbers /* ... assignments*/
...
More generally,the strings would not be restricted to contain only assignment
statements,but could include any valid ARexx statements. The Clip List could
thus provide a series of programs for initializations or other processing
tasks.
The resident process supports addition and deletion operations for maintaining
the Clip List. The names in the(name,value)pairs are assumed to be in mixed
cases,and are maintained to be unique in the list. An attempt to add a string
with an existing name will simply update the value string. The name and value
strings are copied when an entry is posted to the list,so the program that adds
an entry is not required to maintain the strings.
Entries posted to the Clip List remain available until explicitly removed. The
Clip List is automatically released when the resident process exits.
87
CHAPTER 10 INTERFACING TO AREXX
This chapter discusses the issues involved in designing and implementing an
interface between ARexx and an external applications program. The material
presented here is directed to software developers,so a high degree of
familiarity with programming the Amiga in either "C" or assembly-language is
assumed.
ARexx can interact with external programs in several ways. The command
interface is used to communicate with an external program running as a separate
task in the Amiga's multitasking environment. The interaction takes place by
passing messages between public message ports,and is in many ways similar to
the interaction of a program with Intution,the Amiga's window and menu manager.
The command interface provides both a means of sharing data and a method of
controlling an applications program.
Function libraries provide a mechanism for calling external code as part of an
ARexx program's tasks context. The linkages for such calls are established
dynamically at run time rather than when the program is linked,so each function
library must include an entry point to match function names with the address of
the function to be called.
Function hosts are external tasks that manage a public message port for
communicating with ARexx or other programs. Both function hosts and function
libraries are managed by the Library List,which provides a prioritized search
mechanism for resolving function names. Function hosts may be used as a gateway
into a metwork to provide a remote procedure call facility. ARexx imposes no
constraints on the internal operations of a function host,except to require
that message packets be returned with an appropriate code.
The resident process acts as the hub for communications between ARexx and
external entities. It opens and manages a public message port named "REXX," and
provides a number of support services. Note that the resident process is itself
a "host application" whose function it is to launch ARexx programs and maintain
global resources. The activation structures for all ARexx programs are linked
into a list maintained by the resident process,and in principle their compete
internal states are accessible to external programs.
The ARexx interpreter is structured as an Amiga shared library and includes
entry points specifically designed to help implement an interface to ARexx.
Functions are available to create and delete message packets,argument
strings,and other resources. Software developers are rged to use these library
routines whenever possible,as they provide "safe" access to the internal
structures. The ARexx Systems Library functions are documented in Appendix C.
The distribution disk contains the INCLUDE files required to required to work
with the library and data structures.
89
10-1 BASIC STRUCTURES
Most developers will need to work with only two of the data structures used by
ARexx. The RexxArg structure is used for all of the strings manipulated by the
interpreter. It is usually passed as an argstring,a pointer offset from the
structure base that may be treated like an ordinary string pointer. The RexxMsg
structure is an extension of an EXEC Message,and is the message packet used for
all communications with external programs.
ARGSTRINGS. All ARexx strings are maintained as RexxArg structures,which are
diagrammed in Table 10.1 below. Note that his actually a variable-length
structure allocated for each specific string length. String parameters are sent
in the form of argstrings,a pointer to the string buffer area of the RexxArg
structure. The string in the stucture is always given a trailing null byte,so
that external programs can treat argstrings like a pointer to a null-terminated
string. Additional data about the string(its length,hash code,and attributes)
are available at negative offsets from the argstring pointer.
Table 10.1 The RexxArg Structure
STRUCTURE RexxArg,0
LONG ra_Size ; allocated length
UWORD ra_Length ; length of string
UBYTE ra_Flags ; attribute flags
UBYTE ra_Hash ; hash code
STRUCT ra_Buff,8 ; buffer (argstring points here)
Library functions are available to create and delete argstrings,and for
converting integers into argstring format. The function CreateArgstring()
allocates a structure and copies a string into it,and returns an argstring
pointer to the structure. The function DeleteArgstring()can be used to release
an argstring when it is no longer needed.
MESSAGE PACKETS. All communications between ARexx and external programs are
mediated with with message packets,whose structure is diagrammed in Table 10.2
below. Functions are provided in the ARexx Systems Library to create,
initialize,and delete these message packets. Each packet sent from ARexx to an
external program is marked with a special pointer in its name field. This can
be used to distinguish the message packets from those belonging to other
programs,in case a message port is being shared.
Message packets are created using the CreateRexxMsg()function,and can be
released using the DeleteRexxMsg(). Note that the message packets passed by
ARexx to a host application(as a command,for instance)are identical to the
packets the host would use to invoke an ARexx program. This commonality of
design means that only one set of functions is needed to create and delete
message packets,and that external programs can use the same routines that the
interpreter uses to handle the packets.
RESOURCE NODES. A somewhat higher-level data structure called a "resource node"
(a RexxRsrc structure)is used extensively within ARexx to maintain resource
lists. These nodes are variable-length structures that include the total
allocated length as a field within the node,and that also provide for an
"auto-delete" function. This latter capability allows the address of a clean-up
90
function to be associated with the node so that an entire(possibly
inhomogeneous)list of resource nodes can be deallocated with a single function
call.
Table 10.2 The RexxMsg Structures
STRUCTURE RexxMsg,MN_SIZE
APTR rm_TaskBlock ; global pointer
APTR rm_LibBase ; library pointer
LONG rm_Action ; command code
LONG rm_Result1 ; primary result
LONG rm_Result2 ; secondary result
STRUCT rm_Args,16*4 ; arguments (ARGO-ARG15)
; the extension area
APTR rm_PassPort ; forwarding port
APTR rm_CommAddr ; host address
APTR rm_FileExt ; file extention
LONG rm_Stdin ; input stream
LONG rm_Stdout ; output steam
LONG rm_avail ; reserved
LABEL rm_SIZEOF ; 128 bytes
10-2 DESIGNING A COMMAND INTERFACE
The minimal command interface between ARexx and an applications program
requires only a public message port and a routine to process the commands
received. For most host applications this will require little extra machinery,
as the program will probably already have several message ports for key and
menu events,timer messages,and so on. Processing the command strings should be
relatively straightforward for command-oriented applications. Hosts that are
entirely menu-driven will require somewhat more additional programming,unless
commands are supported only as simulated menu events. The specific choice of
which commands to support is always left up to the applications designer,as
ARexx imposes no restrictions on the structure of the commands that can be
issued.
The basic sequence of events in the command interface begins when the host
sends a command invocation message to the ARexx resident process. This is
usually in response primitives supported by the host. When the resident process
receives the message packet,it spawns a new DOS process the run the macro
program. The command line is parsed to extract the command token(the first
word),and the interpreter searches for a file that matches the command name.
Once a macro program file has been found,it is executed by the interpreter and
(usually)results in one or more commands being issued back to the host
application's public port. The macro program waits while each command is
processed by the host,and takes appropriate actions if the return code
indicates that an error occurred. Eventually the macro program finishes and
returns the invocation message packet back to the host.
Error handling is an important consideration in the interface design. Macro
programs must receive return codes so that processing actions can be altered
when errors occur.
91
Normally,the host application should not return a message packet until the
command has been processed and its error status in known. Hosts that support
two streams of commands(from the user and from the command interface)will need
a flag to indicate the source of each command. Errors in user commands might
normally be reported on the screen,but errors in ARexx commands must be
reported by setting the result field in the message packet.
Return codes should generally be chosen to follow the model of an error
severity level,with small integers representing relatively harmless conditions
and larger values indicating progressively more severe errors. This will allow
a characteristic failure level to be established within a macro program,so that
insignificant errors can be ignored. The choice of the specific return code
values is left to the applications designer.
RECEIVING COMMAND MESSAGES
Each host application must open a public message port to support the command
interface. When a macro program issues a command to the host,a message packet
containing the command is sent to this public port. The structure of these
message packets is shown in Table 10.2. The rm_Action field will be set to
RXCOMM,and the ARGO parameter slot will contain the command as an argstring
pointer. Parameter slots ARG1-ARG15 are not used for command messages. Two
other fields are potentially of interest: the rm_RexxTask field contains a
pointer to the global data structure for the program that issued the command,
and the rm_LibBase field has the ARexx library base address. The fields in the
extension area may also be of interest to the host program;these are described
later on. Except for setting the result fields rm_Result1 and rm_Result2,the
host application should not alter the message packet.
RESULT FIELDS
When the host program finishes processing the command,it must set the primary
result field rm_Result1 to an error severity level or zero if no errors
occurred. This is the field which will be assigned to the special variable RC
in the macro program. The secondary result field rm_Result2 should be set to
zero unless a result string(as described below)is being returned. The packet
can then be returned to the sender using the EXEC function ReplyMsg().
In some cases a macro program may request a result string by setting the
RXFB_RESULT modifier bit in the command code. If possible,the host application
should then return the result as an argstring pointer in the secondary result
field rm-Result2. A result string should only be returned if explicitly
requested and if no errors occurred during the call(rm_Result1 set to zero).
Failure to observe these rules will result either in memory loss or in
corruption of the system free-memory list.
MULTIPLE HOST PROCESSES
Many applications programs support concurrent activities on several sets of
data. For example,most text editors allow several files to be edited at once. A
command issued from a particular instance of the editor might invoke an ARexx
macro program,so clearly any commands issued from that macro would have to be
directed to the correct instance of the editor. ARexx provides for this by
92
allowing the applications program to declare an initial host address when a
program is invoked. A separate message port would be opened for each instance
of the host application,and this port would be named as the initial host
address for all invocations from that instance. In the example above,if the
editor opened two ports named "MyEdit1" and "MyEdit2,"then programs invoked by
the "MyEdit1" instance would send commands back to the "MyEdit1" port.
MULTIPLE MESSAGE PORTS. Host applications are not limited to having a single
message port for commands. If several different kinds of commands are to be
received,it might be appropriate to set up more than one port. Macro programs
would then use the ADDRESS instruction to direct commands to the appropriate
port. The different ports could be used simultaneously,since ARexx programs
execute as separate tasks.
10-3 INVOKING AREXX PROGRAMS
ARexx programs are invoked by sending a message packet to the resident process.
Programs may be invoked as either a command or as a function. The command mode
of invocation is generally simpler,as it requires setting only a few fields in
the message packet.
MESSAGE PACKETS
The structure of the message packet supported by ARexx is shown in Table 10.2.
This structure provides fields for passing arguments and for specifying
overrides to various internal defaults. The packets are cleared(set to 0)when
allocated,and the client-supplied fields are never altered by ARexx. Message
packets can be reused after being returned,and generally only one is required.
COMMAND(ACTION)CODE. The rm_Action field of the message packet determines the
mode of invocation. It can be set to either RXCOMM or RXFUNC for command or
function mode,respectively. Several modifier flags can be used with the command
code;these are described later in this chapter.
ARGUMENT STRINGS. Command strings,function names,and argument strings must be
supplied as argstrings. Strings can be conveniently packaged into argstrings
using the CreateArgstring()library function,which takes a string pointer and a
length as its arguments. Argstrings point to a null-terminated string and may
be treated like an ordinary string pointer in most cases. In principle,a host
application could build the argstrings directly,but since the strings must
remain unchanged for the duration of a ARexx program,the host might need to
maintain many such structures.
The argstrng pointer returned by CreateArgstring()is installed in the
appropriate parameter slot of the message package:ARGO for the command string
or function name,and ARG1-ARG15 for argument strings. Argstrings can be
recycled after a packet has returned by calling the DeleteArgstring() function.
SENDING THE PACKET. Once the required fields have been filled in,the host
application can send the packet to the "REXX" public port using the EXEC
function PutMsg(). The address of the "REXX" port can be obtained by a call to
the FindPort()function,but this address should not be cached internally,since
the port could close at any time. To be absolutely safe,the calls to FindPort()
and PutMsg()should be bracketed by calls to the EXEC routines Forbid()and
Permit(). This will exclude the slight possibility that the message port could
close in the few microseconds before the message packet is actually sent to the
port address.
After sending the packet the host can return to its normal processing,since the
macro program will execute as a separate task. In most cases it will be
advisable to "lock-out" further user commands while the ARexx program is
running,to preserve te integrity of any shared data structures that may be
accessed externally.
COMMAND INVOCATIONS
In the command mode of invocation the host supplies a command string consisting
of a name token followed by an argument string. ARexx parses the string to
extract the command name,which is usually the name of a program file. The
default action is to use the remainder of the command string as the(single)
argument string for the program. This may be overridden by requesting command
tokenization,which is done by setting the RXFB_TOKEN modifier flag in the
action code of the message packet. In this case the entire command string will
be parsed,and the program may have many argument strings.(There is no limit to
the number of arguments that may be derived from the command string,since they
don't have to fit into the parameter slots of the message packet.)
The parsing process uses "white space" (blanks,tabs,etc.)as the token
separators,and has a several special features.
QUOTING CONVENTION. Either single(')or double(")quotes may be used to surround
items that include "white space" and would otherwise be separated during
parsing. Single quotes may appear within a double-quote-delimited token,and
vice versa;however,double-delimiter sequences are not accepted. The quotes are
removed from the parsed token. An "implicit" quote at the end of the string is
also recognized. If the command string ends before the closing delimiter has
been found,the null byte is accepted as the final delimiter. For example,
look.rexx "Now is the time" "can't ou see
is a command with the two arguments strings "Now is the time" and "can't you
see"(but without the quotes.)
STRING FILES. If the command name(the first token of the string)is quoted,it is
assumed to be a "string file" --an ARexx program in a string,rather than the
name of a disk file. This is a convenient way to run very brief programs,
although programs of any length may be stored this way. If command tokenization
has not been specified,the remainder of the string is not scanned and no quote
characters are removed. In this case the quoting convention isuseful only for
indicating "string file" programs. The entire command string can be declared as
a "string file" by setting the RXFB_STRING modifier flag of the action code.
When this flag is set,no parsing at all is applied to the command.
RESULT STRING. Command invocations do not usually request a result string,but
can do so by setting the RXFB_RESULT modifier flag. The host application must
be prepared to recycle the returned result string once it is no longer needed.
94
FUNCTION INVOCATIONS
In a function invocation the host application supplies a function name string
and from 0 to 15 argument strings. The name string is used to locate an
external program file and may include directory specifiers and a file
extension. The actual argument count(not including the name string)must be
placed in the low-order byte of the command code.
This mode of invocation is normally used when a result string is expected and
the argument strings are conveniently available. Note that a result does not
have to be requested,however.
RESULT STRINGS. Function invocations request a result string by setting the
RXFB_RESULT modifier flag bit. If no errors occurred and a result string was
requested,the secondary result field in the returned packet will be a pointer
to the result string. However,if the program exited without supplying a result,
the secondary field will be zero.
STRING FILES. The function name argument may specify a "string file" rather
than the name of a filing system object. This is indicated by setting the
RXFB_STRING modifier flag.
SEARCH ORDER
The search for a program file matching a command or function name is normaly a
two-step process. For each directory to be checked,a search is made first with
the current file extension appended to the name string. If this search fails,
the second search uses the unmodified name string. The first step is skipped if
the command or function name includes an explicit file extension.
The default file extension is ".rexx,"but this can be changed by supplying a
file extension string in an extended message packet. Host applications will
usually specify a file extension,since it provides a convenient way to
distinguish the macro programs that are specific to that application. Refer to
the section on Extension Fields for further details.
The search path for a program depends on the way the program name was
specified. If an explicit device or directory specification precedes the
program name,only that directory will be searched. For example,the command-
level invocation of "rx df0:s/test" will search only the df0:s directory for a
file named test.rexx or test. If the program name does not include a path,the
search path begins with the current directory and proceeds to the system REXX:
directory. To further the above example,invoking the program as "rx test 1 2 3"
would search for the files test.rexx,test,REXX:test.rexx,and REXX:test,in that
order.
If an ARexx program cannot be found,one alternative action may be taken. If the
rm_PassPort field of an extended packet was supplied,the message packet is
passed along to that port,which might be the next process in a search chain.
Otherwise the message is returned with a "Program not found"error indication
(error code 1.)
95
EXTENSION FIELDS
The RexxMsg structure includes several "extension fields" that can be used to
override various defaults when a program is invoked. These extension fields can
be filled in selectively,and only the non-zero values will override the
corresponding default. ARexx never modifies the extension area.
Host applications should supply values for the file extension and host address
fields of the message packet. The file extension affects which program files
will match a given command name,and allows macro programs specific to the host
to be given distinctive names. The host address must refer to a public message
port,and will usually indicate the host's own port. Any appropriate(but usually
short)strings can be chosen for these values. Oftern,the name of the
applications program itself can be used as its host address and file extension.
PASSPORT. The rm_PassPort field allows the search for a program to be "passed
along" to another messsage port after checking for an ARexx program. If the
command or function name doesn't resolve to an ARexx program,the message packet
is forwarded to the message port specified as the PassPort. This allows
applications to maintain control over the search order for external program
files.
Note that the rm_PassPort field must be the actual address of a message port,
rather than a name string. The PassPort therefore does not have a public port,
but the port should be a secured resource,since the message is sent directly to
this address without checking to see whether it is a valid message port.
HOST ADDRESS. The rm_ComAddr field overrides the default initial host address,
which is "REXX." The host address is the name of the messsage port to which
commands will be directed,and is supplied as a pointer to a null-terminated
string. Applications that support multiple instances of user data will usually
create a separate message port for each instance. The name of this port would
then be supplied as the host address for any commands issued from that
instance.
FILE EXTENSION. The rm_FileExt field is used to override the default file
extension for ARexx programs,which is "REXX". Host applications can use the
file extension to distinguish the names of the macro programs specific to that
application. It is supplied as a pointer to a null-terminated string.
INPUT AND OUTPUT STREAMS. The default input and output steams for an ARexx
program are inherited from the host application's process structure,if the host
is a process rather than just a task. One or both of these streams may be
overridden by supplying an appropriate value in the rm-Stdin or rm_stdout
fields. The values supplied must be valid DOS filehandles,and must not be
closed while the program is executing. The steams are installed directly into
the program's process structure,replacing the prior values.
The output stream is also used as the default tracing stream for the program.
If interactive tracing is to be used in a program,the output stream should
refer to a console device,since it will be used for input as well.
96
In the event than an ARexx program is invoked by an EXEC task,rather than by an
DOS process,the extension field streams are the only way that the launched
program can be given default I/O streams.
INTERPRETING THE RESULT FIELDS
The message packet that invoked an ARexx program is returned to the client when
the program finishes. The two result fields will contain error codes or
possibly a result string. The interpretation of the result fields depends
partly on the mode of invocation. If the primary result field rm_Result1 is
zero,the program executed normally and the secondary field rm_Result2 will
contain a pointer to a result string,assuming that one was requested(and
available.)
If the primary result is non-zero,it represents either an error severity level
or else the return code from a command invocation. The two cases can be
distinguished by examining the secondary result. If the secondary field is also
non-zero,an error occurred and the secondary field is an ARexx error code. If
the secondary result is zero,then the primary result is the return code passed
by an "EXIT rc" or "RETURN rc" instruction in the program. The application
program can use this return code either as an error indication or to initiate
some particular processing action.
Result strings are always returned as an argstring and become the property(that
is,responsibility)of the host. When the string is no longer needed,it can be
released using the DelArgstring() function.
Errors occurring in macro programs should usually be reported to the user.
Explanatory messages are available for all ARexx error codes,and can be
obtained by calling the ARexx Systems Library function ErrorMsg().
10-4 COMMUNICATING WITH THE RESIDENT PROCESS
All communications with the resident process are handled by passing message
packets,which were previously diagrammed in Table 10.2. The packet has a
command field that describes the action to be performed and parameter fields
that are specific to the command. Message packets are processed as they are
received,and are then either returned to the sender or passed along to another
process(in the case of a program invocation.) The packet includes two result
fields that are used to return error codes or result strings. The parameter
fields of the message packet may contain either(long)integer values or pointers
to argument strings. String arguments are assumed to be argstring pointers
unless otherwise specified.
COMMAND(ACTION)CODES
The command codes that are currently implemented in the resident process are
described below. Commands are listed by their mnemonic codes,followed by the
valid modifier flags. The final code value is always the logical OR of the code
value and all of the modifier flags selected. The command code is installed in
the rm_Action field of the message packet.
USAGE: RXADDCON [RXFB_NONRET]
This code specifies an entry to be added to the Clip List. Parameter slot ARGO
points to the name string,slot ARG1 points to the value string,and slot ARG2
contains the length of the value string.
97
The name and value arguments do not need to be argstrings,but can be just
pointers to storage areas. The name should be a null-terminated string,but the
value can contain arbitrary data including nulls.
USAGE: RXADDFH [RSFB_NONRET]
This action code specifies a function host to be added to the Library List.
Parameter slot ARGO points to the(null-terminated)host name string,and slot
ARG1 holds the search priority for the node. The search priority should be an
integer between 100 and -100 inclusive;the remaining priority ranges are
reserved for future extensions. If a none already exists with the same name,the
packet is returned with a warning level error code. Note that no test is made
at this time as to whether the host port exists.
USAGE:RXADDLIB [RXFB_NONRET]
This code specifies an entry to be added to the Library List. Parameter slot
ARGO points to a null-terminated name string referring either to a function
library or a function host. Slot ARG1 is the priority for the node and should
be an integer between 100 and -100 inclusive;the remaining priority ranges are
reserved for future extensions. Slot ARG2 contains the entry oint offset and
slot ARG3 is the library version number. If a node already exists with the same
name,the packet is returned with a warning level error code. Otherwise,a new
entry is added and the library or host becomes available to ARexx programs.
Note that no test is made at this time as to whether the library exists and can
be opened.
USAGE:RXCOMM [RXFB_TOKEN] [RXFB_STRING] [RXFB_RESULT] [RXFB_NOIO]
Specifies a command-mode invocation of an ARexx program. Parameter slot ARGO
must contain an argstring ointer to the command string. The RXFB_TOKEN flag
specifies that the command line is to be tokenized before being passed to the
invoked program. The RXFB_STRING flag bit indicates that the command string is
a "string file." Command invocations do not normally return result strings,but
the RXFB_RESULT flag can be set if the caller is prepared to handle the cleanup
associated with a returned string. The RXFB_NOIO modifier suppresses the
inheritance of the host's input and output streams.
USAGE:RXFUNC [RXFB_RESULT] [RXFB_STRING] [RXFB_NOIO] argcount
This command code specifies a function invoction. Parameter slot ARGO contains
a pointer to the function name string,and slots ARG1 through ARG15 point to the
argument strings,all of which must be passed as argstrings. The lower byte of
the command code is the argument count;this count excludes the function name
string itself. Function calls normally set the RXFB_RESULT flag,but this is not
mandatory. The RXFB_STRING modifier indicates that the function name string is
actually a "string file". The RXFB_NOIO modifier suppresses the inheritance of
the host's input and output streams.
USAGE:RXREMCON [RXFB_NONRET]
This code requests that an entry be removed from the Clip List. Parameter slot
ARGO points to the null-terminated name to be removed. The Clip List is
searched for a node matching the supplied name,and if a match is found the list
node is removed and recycled. If no match is found the packet is returned with
a warning error code.
USAGE:RXREMLIB [RXFB_NONRET]
This command removes a Library List entry. Parameter slot ARGO points to the
null terminated string specifying the library to be removed. The Library List
is searched for a node matching the library name,and if a match is found the
98
node is removed and released. If no match is found the packet is returned with
a warning error code. The libary node will not be removed if the library is
currently being used by an ARexx program.
USAGE:RXTCCLS [RXFB_NONRET]
This code requests that the global tracing console be closed. The console
window will be closed immediately unless one or more ARexx programs are waiting
for input from the console. In this event,the window will be closed as soon as
the active programs are no longer using it.
USAGE:RXTCOPN [RXFB_NONRET]
This command requests that the global tracing console be opened. Once the
console is open,all active ARexx programs will divert their tracing output to
the console. Tracing input(for interactive debugging)will also be diverted to
the new console. Only one console can be opened;subsequent RXTCOPN requests
will be returned with a warning error message.
MODIFIER FLAGS
Command codes may include modifier flags to select various processing options.
Modifier flags are specific to certain commands,and are ignored otherwise.
RXFB_NOIO. This modifier is used with the RXCOMM and RXFUNC command codes to
suppress the automatic inheritance of the host's input and output streams.
RXFB_NONRET. Specifies that the message packet is to be recycled by the
resident process rather than being returned to the sender. This implies that
the sender doesn't care about whether the requested action succeeded,since the
returned packet provides the only means of acknowledgement. Messge packets are
released using the library function DeleteRexxMsg().
RXFB_RESULT. This modifer is valid with the RXCOMM and RXFUNC commands,and
requests that the called program return a result string. If the program
EXITs(or RETURNs)with an expression,the expression result is returned to the
caller as an argstring. It is then the caller's responsibility to release the
argstring when it is no longer needed;this can be done using the library
function DeleteArgstring().
RXFB_STRING. This modifer is valid with the RXCOMM and RXFUNC command codes. It
indicates that the command or function argument(in slot ARGO)is a "string file"
rahter than a file name.
RXFB_TOKEN. This flag is used with the RXCOMM code to request that the command
string be completely tokenized before being passed to the invoked program.
Programs invoked as commands normally have only a single argument string. The
tokenization process uses "white space" to separate the tokens,except within
quoted strings. Quoted strings can use either single or double quotes,and the
end of the command string(a null character)is considered as an implicit closing
quote.
99
RESULT FIELDS
The resident process uses the standard command-level conventions for the
primary return code installed in rm_Result1. Minor or warning errors are
indicated by a value of 5,and more serious errors are returned as values of 10
or 20. The secondary result field rm-Result2 will either be zero or an ARexx
error code if applicable.
Note that RXCOMM and RXFUNC messages are returned directly by the invoked macro
program,rathe than by the residen process.
10-5 EXTERNAL FUNCTION LIBRARIES
ARexx supports external function libraries as a mechanism for user-defined
extensions to the language. Function libraries may be written and maintained by
users or applications developers.
DESIGN CONSIDERATIONS
There are several different purposes for which a function library might be
designed. In the simplest case,a library could be used to extend the string
manipulation or mathematical capabilities of the language by defining new
functions. Such a library could be entirely self-contained or might call other
system libraries to perform specific operations.
Another alternative would be to build a library that interacts closely with an
external applications program. This could allow specific operations in the host
application to be performed as function calls rather than as commands. There
are several advantages to this approach,as it avoids the need to parse command
strings and does not require the multiple task context changes associated with
message-passing. The library might include entry points for specific operaions
as well as functions to support processing required by the applications
program.
Function libraries can also serve as bridges to other system or applications
libraries. For example,if a program needed to call the functions in a graphics
library,a bridge library could be built to match the function names in the
program with the appropriate entry point in the graphics library. A related
possibility would be to use ARexx as a test driver for a program under
development. Once the query table and parameter passing mechanisms for the
function library have been built,new routines under development could be tested
by just adding a table entry. Since building test programs is ofter very time-
consuming,the flexibility and interactive debugging capabilities of ARexx make
it an attractive alternative to compiled languages like "C."
Regardless of the intended application,all function libraries share a common
structure. The initial design follows that of the standard EXEC shared library,
with the three required entry points Open,Close,and Expunge,plus a reserved
slot. The library must also have a "query" entry point,which serves to match
the name supplied by ARexx with the intended function. Typically,this will
consist of a table of function names and a routine to search for the specified
one.
REENTRANCY. Functions libraries should be designed to be fully reentrant,since
any number of ARexx programs may be running at any time. If this is not
feasible due to other design constraints,the query function should include a
lockout mechanism to prevent multiple calls to the library routines.
100
CALLING CONVENTION
The library's query function will be called from the interpreter's context with
the address of a message packet in register A0 and the library base in A6. The
structure of the message packet is the same as that in Table 10.2,but note that
although a message packet is used to carry the arguments,it is not queued at a
message port and does not need to be unlinked. The name of the function to be
called is carried in the ARGO parameter slot. The query function must search
for this function name and,if the name cannot be found,must return an error
code of 1("Program not found")in register D0. The library will then be closed
and the search continued in the next function library. The query function
should not modify any fields within the message packet,as it must be passed
along to the next library until the function is located.
PARAMETER CONVERSION
Once the requested function has been found,the query funcion may need to
transform the parameters passed by ARexx into the form expected by the
function. Whether the parameter strings need to be converted depends on how
they are to be used. In some cases it may be sufficient just to foward a
pointer to the message packet to the called function,while in other cases the
query function may need to load parameters into registers or to perform
conversion operations. The parameters in ARG1-ARG15 are always passed as
argstrings,and may be treated like a pointer to a null-terminated string.
Further attributes are stored at negative offsets from the argstring pointer,
and may be helpful in working with the string.
Numeric quantities are passed as strings of ASCII characters and will need to
be converted to integer or floating-point format if arithmetic calculations are
to be performed. The ARexx System Library includes a limited set of functions
to do parameter conversions.
The actual parameter count can be obtained from the low-order byte of the
rm_Action field in the message packet. The count never includes the function
name itself(in ARGO),but does include arguments specified as "defaults." Such
arguments will have a zero value in the corresponding parameter slot.
Note that the parameter block of the message packet,containing the fields
ARG0-ARG15,is structured like the argument array expected by the main(argc,
argv)function of a "C" program. This suggests a simple way that a function
library could provide a bridge to a series of "C" programs. The query function
would need only to determine the address of the called function,and then push
the parameter block address and argument count onto the program stack.
RETURNED VALUES
Each library function must return an error code and a value string. The error
code is returned in register D0,and should be 0 if no errors occurred. The
value string must be returned as an argstring pointer in register A1,unless D0
indicates that an error occurred during the call. The mechanisms for creating
the proper return values can be made part of the query function,so that all
functions in the library share a common return path.
101
10-6 DIRECT MANIPULATION OF DATA STRUCTURES
All of the data structures maintained by the resident process are built into
the ARexx Systems Library base and are therefore accessible to external
programs. The Task List in the RexxBase structure links the global data
structures for all currently active ARexx programs. This linkage uses the node
contained in the message port of the RexxTask structure,rather than at the head
of the structure. The RexxTask structure is the global data structure and
initial storage environment for the ARexx program,and all descendant storage
environments are linked into the Environment List. The linkage of internal data
structures is such that the complete internal state of all ARexx programs can
be reached starting from the library base pointer.
Two library functions,LockRexxBase() and UnlockRexxBase(),are provided to
mediate access to the global structures. The structure base should be locked
before reading any of the data items or traversing any of the lists. The
present version of these functions provides only a global lock,but future
extensions will allow individual resources to be locked.
In general it should not be necessary to manipulate directly any of these data
structures. Functions have been provided in the ARexx Systems Library to
perform all of the operations required to interface external program to the
ARexx system. It is therefore recommended that applictions developers avoid
using any of the internal structures except as provided through the library
functions.
102
APPENDIX A ERROR MESSAGES
When the ARexx interpeter detects an error in a program,it returns an error
code to indicate the nature of the problem. Errors are normally handled by
displaying the error code,the source line number where the error occurred,and a
brief message explaining the error condition. Unless the SYNTAX interrupt has
been previously enabled(using the SIGNAL instruction),the program then
terminates and control returns to the caller. Most syntax and execution errors
can be trapped by the SYNTAX interrupt,allowing the user to retain control and
perform whatever special error processing is required. Certain errors are
generated outside of the context of an ARexx program,and therefore cannot be
trapped by this mechanism. Refer to chapter 7 for further information on error
trapping and processing.
Associated with each error code is a severity level that is reported to the
calling program as the primary result code. The error code itself is returned
as the secondary result. The subsequent propagation or reporting of these codes
is of course dependent on the external(calling)program.
The following pages list all of the currently-defined error codes,along with
the associated severity level and message string.
ERROR: 1 SEVERITY: 5 MESSGE: PROGRAM NOT FOUND
The named program could not be found,or was not an ARexx program. ARexx
programs are expected to start with a "/*" sequence. This error is detected by
the external interface and cannot be trapped by the SYNTAX interrupt.
ERROR: 2 SEVERITY: 10 MESSAGE: EXECUTION HALTED
A control-C break or an external half request was received and the program
terminated. This error will be trapped if the HALT interrupt has been enabled.
ERROR: 3 SEVERITY: 20 MESSAGE: INSUFFICIENT MEMORY
The interpreter was unable to allocate enough memory for an operation. Since
memory space is required for all parsing and execution operations,this error
cannot usually be trapped by the SYNTAX interrupt.
ERROR: 4 SEVERITY: 10 MESSAGE: INVALID CHARACTER
A non-ASCII character was found in the program. Control codes and other non-
ASCII characters may be used in a program by defining them as hex or binary
strings. This is a scan phase error and cannot be trapped by the SYNTAX
interrupt.
ERROR: 5 SEVERITY: 10 MESSAGE: UNMATCHED QUOTE
A closing single or double quote was missing. Check that each string is
properly delimited. This is a scan phase error and cannot be trapped by the
SYNTAX interrupt.
103
ERROR: 6 SEVERITY: 10 MESSAGE: UNTERMINATED COMMENT
The closing "*/" for a comment field was not found. Remember that comments may
be nested,so each "/*" must be matched by a "*/." This is a scan phase error
and cannot be trapped by the SYNTAX interrupt.
ERROR: 7 SEVERITY: 10 MESSAGE: CLAUSE TOO LONG
A clause was too long for the internal buffer used as temporary storage. The
source line in question should be broken into smaller parts. This is a scan
phase error and cannot be trapped by the SYNTAX interrupt.
ERROR: 8 SEVERITY: 10 MESSAGE: INVALID TOKEN
An unrecognized lexical token was found,or a clause could not be properly
classified. This is a scan phase error and cannot be trapped by the SYNTAX
interrupt.
ERROR: 9 SEVERITY: 10 MESSAGE: SYMBOL OR STRING TOO LONG
An attempt was made to create a string longer than the maximum supported by the
interpreter. The implementation limits for internal structure are given in
Appendix B.
ERROR: 10 SEVERITY: 10 MESSAGE: INVALID MESSAGE PACKET
An invalid action code was found in a message packet sent to the ARexx resident
process. The packet was returned without being processed. This error is
detected by the external interface and cannot be trapped by the SYNTAX
interrupt.
ERROR: 11 SEVERITY: 10 MESSAGE: COMMAND STRING ERROR
A command string could not be processed. This error is detected by the external
interface and cannot be trapped by the SYNTAX interrupt.
ERROR: 12 SEVERITY: 10 MESSAGE: ERROR RETURN FROM FUNCTION
An external function returned a non-zero error code. Check that the correct
parameters were supplied to the function.
ERROR: 13 SEVERITY: 10 MESSAGE: HOST ENVIRONMENT NOT FOUND
The message port corresponding to a host address string could not be found.
Check that the required external host is active.
ERROR: 14 SEVERITY: 10 MESSAGE: REQUESTED LIBRARY NOT FOUND
An attempt was made to open a function library included in the Library List,but
the library could not be opened. Check that the correct name and version of the
library were specified when the library was added to the resource list.
ERROR: 15 SEVERITY: 10 MESSGE: FUNCTION NOT FOUND
A function was called that could not be found in any of the currently
accessible libraries,and could not be located as an external program. Check
that the appropriate function libraries have been added to the Libraries List.
104
ERROR: 16 SEVERITY: 10 MESSAGE: FUNCTION DID NOT RETURN VALUE
A function was called which failed to return a result string,but did not
otherwise report an error. Check that the function was programmed correctly,or
invoke it using the CALL instruction.
ERROR: 17 SEVERITY: 10 MESSAGE: WRONG NUMBER OF ARGUMENTS
A call was made to a function which expected more(or fewer)arguments. This
error will be generated if a Built-In or external function is called with more
arguments than can be accomodated in the message packet used for external
communications.
ERROR: 18 SEVERITY: 10 MESSAGE: INVALID ARGUMENT TO FUNCTION
An inappropriate argument was supplied to a function,or a required argument was
missing. Check the parameter requirements specified for the function.
ERROR: 19 SEVERITY: 10 MESSAGE: INVALID PROCEDURE
A PROCEDURE instruction was issued in an invalid context. Either no internal
functions were active,or a PROCEDURE had already been issued in the current
storage environment.
ERROR: 20 SEVERITY: 10 MESSAGE: UNEXPECTED THEN OR WHEN
A WHEN or THEN instruction was executed outside of a valid context. The WHEN
instruction is valid only within a SELECT range,and THEN must be the next
instruciton following an IF or WHEN.
ERROR: 21 SEVERITY: 10 MESSAGE: UNEXPECTED ELSE OR OTHERWISE
An ELSE or OTHERWISE was found outside of a valid context. The OTHERWISE
instruction is valid only within a SELECT range. ELSE is valid only following
the THEN branch of an IF range.
ERROR: 22 SEVERITY: 10 MESSAGE: UNEXPECTED BREAK,LEAVE,or ITERATE
The BREAK instruction is valid only within a DO range or inside an INTERPRETed
string. The LEAVE and ITERATE instuctions are valid only within an iterative DO
range.
ERROR: 23 SEVERITY: 10 MESSAGE: INVALID STATEMENT IN SELECT
A invalid statement was encountered within a SELECT range. Only WHEN,THEN,and
OTHERWISE statements are valid within a SELECT range,except for the conditional
statements following THEN or OTHERWISE clauses.
ERROR: 24 SEVERITY: 10 MESSAGE: MISSING OR MULTIPLE THEN
An expected THEN clause was not found,or another THEN was found after one had
already been executed.
ERROR: 25 SEVERITY: 10 MESSAGE: MISSING OTHERWISE
None of the WHEN clauses in a SELECT succeeded,but no OTHERWISE clause was
supplied.
ERROR: 26 SEVERITY: 10 MESSAGE: MISSING OR UNEXPECTED END
The program source ended before an END was found for a DO or SELECT instruction
or an END was encountered outside of a DO or SELECT range.
105
ERROR: 27 SEVERITY: 10 MESSAGE: SYMBOL MISMATCH
The symbol specified on an END,ITERATE,or LEAVE instruction did not match the
index variable for the associated DO range. Check that the active loops have
been nested properly.
ERROR: 28 SEVERITY: 10 MESSAGE: INVALID DO SYNTAX
An invalid DO instruction was executed. An initializer expression must be given
if a TO or BY expression is specified,and a FOR expression must yield a non-
negative integer result.
ERROR: 29 SEVERITY: 10 MESSAGE: INCOMPLETE IF OR SELECT
An IF or SELECT range ended before all of the required statement were found.
Check whether the conditional statement following a THEN,ELSE,or OTHERWISE
clause was omitted.
ERROR: 30 SEVERITY: 10 MESSAGE: LABEL NOT FOUND
A label specified by a SIGNAL instruction,or implicitly referenced by an
enabled interrupt,could not be found in the program source. Labels defined
dynamically by an INTERPRET instruction or by interactive input are not
included in the search.
ERROR: 31 SEVERITY: 10 MESSAGE: SYMBOL EXPECTED
A non-symbol token was found where only a symbol token is valid. The DROP,END,
LEAVE,ITERATE,and UPPER instructions may only be followed by a symbol token,and
will generate this error if anything else is supplied. This message will also
be issued if a required symbol is missing.
ERROR: 32 SEVERITY: 10 MESSAGE: SYMBOL OR STRING EXPECTED
An invalid token was found in a context where only a symbol or string is valid.
ERROR: 33 SEVERITY: 10 MESSAGE: INVALID KEYWORD
A symbol token in an instruction clause was identified as a keyword,but was
invalid in the specific context.
ERROR: 34 SEVERITY: 10 MESSAGE: REQUIRED KEYWORD MISSING
An instuction clause required a specific keyword token to be present,but it was
not supplied. For example,this messge will be issued if a SIGNAL ON instruction
is not followed by one of the interrupt keywords(e.g.SYNTAX.)
ERROR: 35 SEVERITY: 10 MESSAGE: EXTRANEOUS CHARACTERS
A seemingly valid statement was executed,but extra characters were found at the
end of the clause.
ERROR: 36 SEVERITY: 10 MESSAGE: KEYWORD CONFLICT
Two mutually exclusive keywords were included in an instruction clause,or a
keyword was included twice in the same instruction.
ERROR: 37 SEVERITY: 10 MESSAGE INVALID TEMPLATE
The template provided with an ARG,PARSE,or PULL instruction was not properly
constructed. Refer to Chapter 8 for a description of template structure and
processing.
106
ERROR: 38 SEVERITY: 10 MESSAGE: INVALID TRACE REQUEST
The alphabetic keyword supplied with a TRACE instruction or as the argument to
the TRACE()Built-In function was not valid. Refer to Chapter 7 for the valid
TRACE options.
ERROR: 39 SEVERITY: 10 MESSAGE: UNINITIALIZED VARIABLE
An attempt was made to use an uninitialized variable while the NOVALUE
interrupt was enabled.
ERROR: 40 SEVERITY: 10 MESSAGE: INVALID VARIABLE NAME
An attempt was made to assign a value to a fixed symbol.
ERROR: 41 SEVERITY: 10 MESSAGE: INVALID EXPRESSION
An error was detected during the evaluation an expression. Check that each
operator has the correct number of operands,and that no extraneous tokens
appear in the expression. This error will be detected only in expressions that
are actually evaluated. No checking is performed on expressions in clauses that
are being skipped.
ERROR: 42 SEVERITY: 10 MESSAGE: UNBALANCED PARENTHESE
An expression was found with an unequal number of opening and closing
parentheses.
ERROR: 43 SEVERITY: 43 MESSAGE: NESTING LIMIT EXCEEDED
The number of subexpressions in an expression was greater than the maximum
allowed. The expression should be simplified by breaking it into two or more
intermediate expressions.
ERROR: 44 SEVERITY: 10 MESSAGE: INVALID EXPRESSION RESULT
The result of an expression was not valid within its context. For example,this
messge will be issued if an increment or limit expression in a DO instruction
yields a non-numeric result.
ERROR: 45 SEVERITY: 10 MESSAGE: EXPRESSION REQUIRED
An expression was omitted in a context where one is required. For example,the
SIGNAL instruction,if not followed by the keywords ON or OFF,must be followed
by an expression.
ERROR: 46 SEVERITY: 10 MESSAGE: BOOLEAN VALUE NOT 0 OR 1
An expression result was expected to yield a boolean result,but evaluated to
something other than 0 or 1.
ERROR: 47 SEVERITY: 10 MESSAGE: ARITHMETIC CONVERSION ERROR
A non-numeric operand was used in a operation requiring numeric operands. This
message will also be generated by an invalid hex or binary string.
ERROR: 48 SEVERITY: 10 MESSAGE: INVALID OPERAND
An operand was not valid for the intended operation. This message will be
generated if an attempt is made to divide by 0,or if a fractional exponent is
used in an exponentiation operation.
107
APPENDIX B LIMITS AND COMPATIBILITY
ARexx was designed to adhere closely to the REXX language standard. This
appendix discusses those areas where ARexx departs from the standard.
B-1 LIMITS
Language definitions seldom include predefined limits to the program structures
that can be created. Only a few such restrictions were imposed in implementing
ARexx,and most of the internal structure are limited only by the total amount
of memory available. The current implementation limits are listed below.
LENGTH OF STRINGS. Strings,symbol names,and value strings are limited to a
maximum length of 65,535 bytes.
LENGTH OF CLAUSES. Clauses are limited to a maximum of 800 characters after
removing comments and multiple blanks.
NODES IN COMPOUND NAMES. Compound symbol names may include a maximum of 50
nodes,including the stem.
ARGUMENTS TO FUNCTIONS. Built-In and external functions are limited to a
maximum of 15 arguments. There is no limit to the number of arguments that may
be passed to an internal function.
SUBEXPRESSION NESTING. The maximum nesting level for subexpressions is 32.
B-2 COMPATIBILITY
ARexx departs in a few ways from the language definition. The differences can
be classified as omissions or extensions,and are described below.
OMISSIONS. The only significant specification of the language standard omitted
from this implementation is the arbitrary-precision arithmetic facility.
Arithmetic operations are limited to about 14 digits of precision,and the FUZZ
option is not implemented at all. Only the SCIENTIFIC format is used for
exponential notation. The full numeric capabilities will be provided in a later
release.
EXTENSIONS. The following extensions to the language standard have been
included in this implementation:
BREAK INSTRUCTION. A new instruction called BREAK has been implemented. It is
used to exit from the scope of any DO or INTERPRET instruction.
ECHO INSTRUCTION. The ECHO instruction has been included as a synonym for SAY.
SHELL INSTRUCTION. The SHELL instructiion has been included as a synonym for
ADDRESS.
109
SIGNAL OPTIONS. Several additional SIGNAL keywords have been implemented.
BREAK_C,BREAK_D,BREAK_E,and BREAK_F will detect and trap the control-C through
control-F signals passed by AmigaDOS. The IOERR keyword traps errors detected
by the I/O system.
STEM SYMBOLS. A stem symbol is valid anywhere that a simple symbol could be
employed.
TEMPLATE PROCESSING. Templates have been generalized in several ways. Variable
symbols may be used as positional tokens if preceded by an operator;the "="
operator is used to denote an absolute position. Multiple templates can be used
with all source forms of the PARSE instruction.
110
APPENDIX C THE AREXX SYSTEMS LIBRARY
The ARexx interpreter is supplied as a shared library named rexxsyslib.library
and should reside in the system LIBS:directory. While many of the library
routines are highly specific to the interpreter,some of the functions will be
useful to applications that use ARexx. The library is opened when the ARexx
resident process is first loaded and will always be available while it remains
active.
The system library routines were designed to be called from assembly-language
programs and,unless otherwise noted,save all registers except for A0/A1 and
D0/D1. Many routines return values in more than one register to help reduce
code size. In addition,the routines will set the condition-code register(CCR)
wherever appropriate. In mode cases the CCR reflects the value returned in D0.
The library offsets are defined in the file rxslib.i,which should be INDLUDEd
in the program source code. Calls may be made from "C" programs if suitable
binding routines are provided when the program is linked. The definitions for
the constants and data structures used in ARexx are provided as INCLUDE files
on the program distribution disk. These should be reviewed carefully before
attempting to use the library functions.
C-1 FUNCTION GROUPS
The library functions can be frouped into Conversion,Input/Output,Resource
Management,and String Manipulation functions.
DATA CONVERSION. These functions provide many of the common data-conversion
requirements.
INPUT/0UTPUT. Two levels of I/O support are provided. The low level functions
use DOS filehandles directly,while the higher-level functions use linked lists
of IoBuff structures and support logical file names.
RESOURCE. These functions allocate,release,or otherwise manage the data
structures used with ARexx.
STRING FUNCTIONS. All data in ARexx are managed as strings. These functions
provide some of the more common string-manipulation operations.
111
TABLE C.1 AREXX SYSTEMS LIBRARY FUNCTIONS
NAME FUNCTIONAL GROUP DESCRIPTION
AddClipNode Resource Allocate a Clip node
ClearMem Resource Clear a block of memory
ClearRexxMsg Resource Release argstrings from message
CloseF Input/Output Close a file buffer
ClosePublicPort Resource Close a port resource node
CmpString String Compare string structures for equality
CreateArgstring Resource Create an argstring structure
CreateDOSPkt Input/Output Creata a DOS Standard Packet
CreateRexxMsg Resource Create a message packet
CurrentEnv Resource Get current storage environment
CVa2i Conversion ASCII to integer
CVc2x Conversion Character to Hex or Binary digits
CVi2a Conversion Integer to ASCII
CVi2arg Conversion Integer to ASCII argstring
CVi2az Conversion Integer to ASCII,leading zeroes
CVs2i Conversion String structure to integer
CVx2c Conversion Hex or binary digits to binary
DeleteArgstring Resource Release an argstring structure
DeleteDOSPkt Input/Output Release a DOS Standard Packet
DeleteRexxMsg Resource Release a message packet
DOSRead Input/Output Read from a DOS filehandle
DOSWrite Input/Output Write to a DOS filehandle
ErrorMsg Conversion Get error message from error code
ExistF Input/Output Check whether a DOS file exists
FillRexxMsg Resource Convert and install argstrings
FindDevice Input/Output Locate a DOS device node
FindRsrcNode Resource Locate a resource node
FreePort Resource Close a message port
FreeSpace Resource Release internal memory
GetSpace Resource Allocate internal memory
InitList Resource Initialize a list header
InitPort Resource Initialize a message port
IsRexxMsg Resource Test a message packet
LengthArgstring Resource Get length of argstring
ListNames Resource Copy node names to an argstring
OpenF Input/Output Open a file buffer
OpenPublicPort Resource Allocate and open a port resource node
QueueF Input/Output Queue a line in a file buffer
ReadF Input/Output Read from a file buffer
ReadStr Input/Output Read a string from a file buffer
RemClipNode Resource Release a Clip node
RemRsrcList Resource Release a resource list
RemRsrcNode Resource Release a resource node
112
TABLE C.1 LIBRARY FUNCTIONS (cont)
NAME FUNCTIONAL GROUP DESCRIPTION
SeekF Input/Output Reposition a file buffer
StackF Input/Output Stack a line in a file buffer
StcToken String Break out a token
StrcmpN String Compare strings
StrcpyA String Copy a string,converting to ASCII
StrcpyN String Copy a string
StrCpyU String Copy a string,converting to uppercase
StrflipN String Reverse characters in a string
Strlen String Find length of a string
ToUpper Conversion ASCII to uppercase
WriteF Input/Output Write to a file buffer
C-2 LIBRARY FUNCTIONS
The following descriptions of the ARexx Systems Library functions are listed
alphabetically. The required arguments and register assignments are shown in
parentheses after the function name. Multiple returns are shown in parentheses
on the left-hand side of the call.
AddClipNode()-allocate and link a Clip node
Usage:node=AddClipNode(list,name,length,value)
D0 A0 A1 D0 D1
A0
(CCR)
Allocates and links a Clip node into the specified list. Clip nodes are
resource nodes containing a name and value string,and include an "auto-delete"
function for simple maintenance. The list argument must point to a properly-
initialized EXEC list header. The name argument points to a null-terminated
name string,the value argument is a pointer to a storage area,and the length
argument is its length in bytes. The returned value is a pointer to the
allocated node,or 0 if the allocation failed.
The RemClipNode()function is installed as the "auto-delete" function for each
node. Clip nodes can be intermixed with other resource nodes in a list and then
released with a single call to RemRsrcList().
See Also:RemClipNode(),RemRsrcList(),RemRsrcNode()
AddRsrcNode()-allocate and link a resource node
Usage:node=AddRsrcNode(list,name,length)
D0 A0 A1 D0
A0
(CCR)
Allocates and links a resource node(a RexxRsrc structure)to the specified list.
The name argument is a pointer to a null-terminated string,a copy of which is
installed in the node structure. The length argument is the total length for
the node;this length is saved within the node so that it may be released later.
113
The returned value is a pointer to the allocated node,or 0 if the allocation
failed.
See Also:RemRsrcList(),RemRsrcNode()
ClearMem()-clear a block of memory
Usage:ClearMem(address,length)
A0 D0
Clears a block of memory beginning at the given address for the specified
length in bytes. The address must be word-aligned and the length must be a
multiple of 4 bytes;all structures allocated by ARexx meet these restrictions.
Register A0 is preserved.
ClearRexxMsg()-release argument strings
Usage:ClearRexxMsg(msgptr,count)
A0 D0
Releases one or more argstrings from a message packet and clears the
corresponding slots. The count argument specifies the number of argument slots
to clear,and can be set to less than 16 to reserve some to the slots for
private use. No action is taken if the slot already contains a zero value.
See Also:FillRexxMsg()
CloseF()-close a file buffer
Usage:boolean=CloseF(IoBuff)
D0 A0
Release the IoBuff structure and closes the associated DOS file. CloseF()is the
"auto-delete" function for the IoBuff structure,so an entire list of file
buffers can be closed with a single call to RemRsrcList().
ClosePublicPort()-close a port resource node
Usage:ClosePublicPort(node)
A0
Unlinks and closes the message port and releases the resource node structure.
The node must have been allocated by the OpenPublicPort()function.
See Also:OpenPublicPort()
CmpString()-compare string structures for equality
Usage:test=CmpString(ss1,ss2)
D0 A0 A1
(CCR)
The arguments ss1 and ss2 must be pointers to ARexx string structures and are
compared for equality. String structures include the length and hash code of
the string,so the actual strings are not compared unless the lengths and hash
codes match. The return value sets the CCR and will be -1(True)if the strings
match and 0(False)otherwise.
114
CreateArgstring()-create an argument string structure
Usage:argstring=CreateArgstring(string,length)
D0 A0 D0
A0
(CCR)
Allocates a RexxArg structure and copies the supplied string into it. The
argstring return is a pointer to the string buffer of the structure,and can be
treated like an ordinary string pointer. The RexxArg structure stores the
structure size and string length at negative offsets to the string pointer. The
string pointer can be set to NULL if only an uninitialized structure is
required.
See Also:DeleteArgstring()
CreateDOSPkt()-allocate and initialize a DOS standard Packet.
Usage:packet = CreateDOSPkt()
D0
A0
(CCR)
Allocates a DOS StandardPacket structure and initializes it by interlinking the
EXEC message and the DOS packet substructures. No replyport is installed in
either the message or the packet,as these fields are generally filled in just
before the message is sent.
See Also:DeleteDOSPkt()
CreateRexxMsg()-allocate an ARexx message packet
Usage: msgptr=CreateRexxMsg(replyport,extension,host)
D0 A0 A1 D0
A0
(CCR)
This function allocates an ARexx message packet from the system free memory
list. The message packet consists of a standard EXEC message structure extended
to include space for function arguments,returned results,and internal defaults.
The replyport argument points to a public or private message port and must be
supplied,as it is required to return the message packet to the sender. The
extension and host arguments are pointers to null-terminated strings that
provide values for the default file extension and the initial host address,
respectively. Additional override fields in the extended packet except for the
primary and secondary result fields rm_Result1 and rm_Result2.
See Also: DeleteRexxMsg()
CVa2i()-convert from ASCII to integer
Usage: (digits,value) = CVa2i(buffer)
D0 D1 A0
Converts the buffer of ASCII characters to a signed long integer value. The
scan proceeds until a non-digit character is found or until an overflow is
detected. The function returns both the number of digits scanned and the
converted value.
115
CVc2x()-convert(unpack)from character string to hex or binary digits.
Usage: error = CVc2x(outbuff,string,length,mode)
D0 A0 A1 D0 D1
Converts the signed integer value argument to ASCII characters using the
supplied buffer pointer. The digits argument specifies the maximum number of
characters that will be copied to the buffer. The returned length is the actual
number of characters copied. The pointer return is the new buffer pointer.
See Also: CVi2az()
CVi2arg()-convert from integer to argstring
Usage: argstring=CVi2arg(value,digits)
D0 D0 D1
A0
(CCR)
Converts the signed long integer value argument to ASCII characters,and
installs them in an argstring(a RexxArg structure). The returned value is an
argstring pointer or 0 if the allocation failed. The allocated structure can be
released using DeleteArgstring().
CVi2az()-convert from integer to ASCII with leading zeroes
Usage: (length,pointer)=CVi2az(buffer,value,digits)
D0 A0 A0 D0 D1
Converts the signed long integer value argument to ASCII characters in the
supplied buffer,with leading zeroes to fill out the requested number of digits.
This function is identical to CVi2a except that leading zeroes are supplied.
See Also:CVi2a()
CVs2i()-convert from string structure to integer
Usage: (error,value)=CVs2i(ss)
D0 D1 A0
The ss argument must be a pointer to a string structure. It is converted to a
signed long integer value return. The error return code is 47("Arithmetic
conversion error")if the string is not a valid number.
116
CVx2c()-convert from hex or binary digits to(packed)string
Usage:error=CVx2c(outbuff,string,length,mode)
D0 A0 A1 D0 D1
Converts the string argument of hex(0-9,A-F)or binary(0,1)digits to the packed
binary representation. The mode argument specifies the(hex or binary)conversion
mode,and must be set to -1 for hex strings or 0 for binary strings. Blank
characters may be embedded in the string for readability,but only at byte
boundaries. The error return code is 47 if the string is not a valid hex or
binary string.
CurrentEnv()-return the current storage environment
Usage:envptr=CurrentEnv(rxtptr)
D0 A0
Returns a pointer to the current storage environment associated with an
executing ARexx program. The rxptr argument is a pointer to the RexxTask
structure,and may be obtained from the message packet sent to an external
application.
DeleteArgstring()-delete(release)an argstring structure
Usage:DeleteArgstring(argstring)
A0
Releases an argstring (RexxArg) structure. The RexxArg structure contains the
total allocated length at a negative offset from the argstring pointer.
See Also:CreateArgstring()
DeleteDOSPkt()-release a DOS Standard Packet structure.
Usage:DeleteDOSPkt(message)
A0
Releases a DOS StandardPacket structure,typically obtained by a prior call to
CreateDOSPkt().
See Also:CreateDOSPkt()
DeleteRexxMsg()-delete(release)an ARexx message packet.
Usage:DeleteRexxMsg(packet)
A0
Release an ARexx message packet to the system free-memory list. The internal
MN-LENGTH field is used as the total size of the memory block to be released,so
this function can be used to release any message packet that contains the total
length in this field. Any embedded argument strings must be released before
calling DeleteRexxMsg().
See Also:CreateRexxMsg()
117
DOSREAD()-read from a DOS file
Usage:count=DOSRead(filehandle,buffer,length)
D0 A0 A1 D0
(CCR)
Reads one or more characters from a DOS filehandle into the supplied buffer.
The length argument specifies the maximum number of characters that will be
read. The returned count is the actual number of bytes transferred,or -1 if an
error occurred.
DOSWrite()-write to a DOS file
Usage:count=DOSWrite(filehandle,buffer,length)
D0 A0 A1 D0
(CCR)
Writes a buffer of the specified length to a DOS filehandle. The retuned count
is the actual number of bytes written,or -1 if an error occurred.
ErrorMsg()-find the message associated with an error code
Usage:(boolean,ss)=ErrorMsg(code)
D0 A0 D0
Returns the error message(as a pointer to a string structure)associated with
the specified ARexx error code. The boolean return will be -1 if the supplied
code was a valid ARexx error code,and 0 otherwise.
ExistF()-check whether an external file exists
Usage:boolean=ExistF(filename)
D0 A0
(CCR)
Tests whether an external file currently exists by attempting to obtain a read
lock on the file. The boolean return indicates whether the operation succeeded,
and the lock is released.
FillRexxMsg()-convert and install arguments in message packet.
Usage:boolean=FillRexxMsg(msgptr,count,mask)
D0 A0 D0 D1
This function can be used to convert and install up to 16 argument strings in a
RexxMsg structure. The message packet must be allocated and the argument fields
of interest set to either a pointer to a null-terminated string or an integer
value. The count argument specifies the number of fields,beginning with ARGO,to
be converted into argstrings and installed into the argument slot. Bits 0-15 of
the mask argument specify whether the corresponding argument is a string
pointer(bit clear)or an integer value(bit set).
118
The count argument is normally set to the exact number of strings to be passed.
By setting this count to less than 16,a number of the slots can be reserved for
private uses.
The returned value is -1(True)if all of the arguments were successfully
converted. In the event of an allocation failure,all of the partial results are
released and a value of 0 is returned.
See Also:ClearRexxMsg()
FindDevice()-check whether a DOS device exists.
Usage:device=FindDevice(devicename,type)
D0 A0 D0
A0
(CCR)
Scans the DOS DeviceList for a device node of the specified type matching the
null-terminated name string. The acceptable values for the type argument are
the constants DLT_DEVICE,DLT_DIRECTORY,or DLT_VOLUME define in the DOS INCLUDE
files. Device names are conveted to uppercase before checking for a match. The
returned value is a pointer to the matched device node,or 0 if the device was
not found.
FindRsrcNode()-locate a resource node with the given name.
Usage:node=FindRsrcNode(list,name,type)
D0 A0 A1 D0
A0
(CCR)
Searchs the specified list for the first node of the selected type with the
given name. The list argument must be a pointer to a properly-initialized EXEC
list header. The name argument is a pointer to a null-terminated string. If the
type argument is 0,all nodes are selected;otherwise,the supplied type must
match the LN_TYPE field of the node. The returned value is a pointer to the
node or 0 if no matching node was found.
FreePort()-release resources associated with a message port
Usage:FreePort(port)
A0
This function deallocates the signal bit associated with a message port and
marks the port as "closed." The task calling FreePort()must be the same one
that initialized the port,since signal bit allocations are specific to a task.
The memory space associated with the port is not released.
See Also:InitPort()
FreeSpace()-releases space to the internal memory allocator.
Usage:FreeSpace(envptr,block,length)
A0 A1 D0
Returns a block of memory to the internal allocator,which must have been
obtained from a call to GetSpace(). The envptr argument is a pointer to the
base or current storage environment.
See Also:CurrentEnv(),GetSpace()
119
GetSpace()-allocate memory using the internal allocator.
Usage:block=GetSpace(envptr,length)
D0 A0 D0
A0
(CCR)
Allocates a block of memory using the internal allocator. The memory is
obtained from an internal pool managed by the interpreter and is returned to
the operating system when the ARexx program terminates. The envptr argument is
a pointer to the base or current storage environment for the program.
The internal allocator must be used to allocate strings for use as values for
symbols,and is convenient for obtaining small blocks of memory whose lifetime
will not exceed that of the ARexx program.
See Also:CurrentEnv(),FreeSpace()
InitList()-initialize a list header
Usage:InitList(list)
A0
Initializes an EXEC list header structure.
InitPort()-initialize a previously-allocated message port.
Usage:(signal,port)=InitPort(port,name)
D0 A1 A0 A1
Initializes a message port structure for which memory space has been previously
allocated,typically as part of a larger structure or as static storage in a
program. It installs the task ID(of the task calling the function)into the
MP_SIGTASK field and allocates a signal bit. The name parameter must be a
pointer to a null-terminated string. The signal return is the signal bit that
was allocated for the port. In the event that a signal could not be assigned,a
value of -1 is returned.
Note that the port is not linked into the system Ports List. If the port is to
be made public,this can be done after the function returns. The port address is
returned in the correct register(A1)for a subsequent call to the EXEC function
AddPort().
See Also:FreePort()
IsRexxMsg()-check whether a message came from ARexx.
Usage:boolean=IsRexxMsg(msgptr)
D0 A0
Tests whether the message packet specified by the msgptr argument came from an
ARexx program. ARexx marks its messages with a pointer to a static string
"REXX" in the LN_NAME field. The returned value is either -1(True)if the
message came from ARexx or 0(False)otherwise.
120
IsSymbol()-check whether a string is a valid symbol.
Usage:(code,length)=IsSymbol(string)
D0 D1 A0
Scans the supplied string pointer for ARexx symbol characters. The code return
is the symbol type if a symbol was found,or 0 if the string did not start with
a symbol character. The length return is the total length of the symbol.
ListNames()-build a string of names from a list.
Usage:argstring=ListNames(list,separator)
D0 A0 D0[0:7]
A0
(CCR)
Scans the specified list and copies the name strings into an argstring. The
list argument must be a pointer to an initialized EXEC list header. The
separator argument is the character,possibly a null,to be placed as a delimiter
between the node names.
The list is traversed inside a Forbid()exclusion and so may be used with shared
or system lists. The returned argstring can be released using DeleteArgstring()
after the names are no longer needed.
See Also:DeleteArgstring()
LockRexxBase()-lock a shared resource.
Usage:LockRexxBase(resource)
D0
Secures the specified resource in the ARexx Systems Library base for read
access. The resource argument is a manifest constant for the required resource,
or zero to lock the entire structure.
Note that write access to shared resources is normally mediated by the ARexx
resident process,which operates at an elevated priority to gain exclusive
access. Locking a resource should not be attempted from a process operating at
a priority higher than the resident process.
See Also:UnlockRexxBase()
OpenF()-open a file buffer
Usage:IoBuff=OpenF(list,filename,mode,logical)
D0 A0 A1 D0 D1
A0
(CCR)
Attempts to open an external file in the specified mode,which should be one of
the constants RXIO_READ,RXIO_WRITE,or RXIO_APPEND defined in the ARexx INCLUDE
files.
121
If successful,an IoBuff structure is allocated and linked into the specified
list. The list argument must be a pointer to a properly-initialized EXEC list
header.
The optional logical argument is the logical name for the file,and must be
either a pointer to a null-terminated string or zero(NULL)if a name is not
required.
See Also:CloseF()
OpenPublicPort()-open a public message port
Usage:node=OpenPublicPort(list,name)
D0 A0 A1
A0
(CCR)
Allocates a message port as an "auto-delete" resource node and links it into
the specified list. The list argument must point to a properly initialized EXEC
list header. The message port is initialized with the given name and linked
into the system Ports List.
See Also:ClosePublicPort()
QueueF()-queue a line to a file buffer.
Usage:count-=QueueF(IoBuff,buffer,length)
D0 A0 A1 D0
Queues a buffer of characters in the stream associated with the IoBuff
structure. The stream must be managed by a DOS handler that supports the
ACTION_QUEUE packet.
Queued lines are placed in "first-in,first-out" order and are immediately
available to be read from the stream. The buffer argument is a pointer to a
string of characters,and the length specifies the number of characters to be
queued. The return value is the actual count of characters or -1 if an error
occurred.
See Also:StackF()
ReadF()-read characters from a file buffer
Usage:count=ReadF(IoBuff,buffer,length)
D0 A0 A1 D0
(CCR)
Reads one or more characters from the file specified by the IoBuff pointer. The
buffer argument is a pointer to a storage area,and the length argument
specifies the maximum number of characters to be read. The return value is the
actual number of characters read,or -1 if an error occurred.
ReadStr()-read a string from a file
Usage:(count,pointer)=ReadStr(IoBuff,buffer,length)
D0 A1 A0 A1 D0
Reads characters from the file specified by the IoBuff pointer until a
"newline" character is found. The "newline" is not included in the returned
string. The return value is the actual number of characters read,or -1 if an
error occurred.
122
See Also:ReadF()
RemClipNode()-unlink and deallocate a list Clip node.
Usage:RemClipNode(node)
A0
Unlinks and releases the specified Clip node. The function is the "auto-delete"
function for Clip nodes,and will be called automatically by RemRsrcNode() or
RemRsrcList().
See Also:AddClipNode(),RemRsrcList(),RemRsrcNode()
RemRsrcList()-unlink and deallocate a list of resource nodes
Usage:RemRsrcList(list)
A0
Scans the supplied list and releases any nodes found. The list must consist of
resource nodes(RexxRsrc structures),which contain information to allow
automatic cleanup and deletion.
See Also:RemRsrcNode()
RemRsrcNode()-unlink and deallocate a resource node
Usage:RemRsrcNode(node)
A0
Unlinks and releases the specified resource node,including the name string if
one is present. If an "auto-delete" function has been specified in the node,it
is called to perform any required resource deallocation before the node is
released.
See Also:RemRsrcList()
SeekF()-seek to the specified position in a file.
Usage:position=SeekF(IoBuff,offset,anchor)
D0 A0 D0 D1
Seeks to a new position in the file is specified by the IoBuff pointer. The
position is given by the offset argument,a byte offset relative to the supplied
anchor argument. The anchor may specify the beginning(-1),the current position
(0),or the end of the file(1). The return value is the new position relative to
the beginning of the file.
StackF()-stack a line to a file buffer.
Usage:count=StackF(IoBuff,buffer,length)
D0 A0 A1 D0
Stacks a buffer of characters in the stream associated with the IoBuff
structure. The buffer argument is a pointer to a string of characters,and the
length specifies the number of characters to be stacked. The return value is
the actual count of characters to be stacked. The return value is the actual
count of characters or -1 if an error occurred.
123
Stacked lines are placed in "last-in,first-out" order and are immediately
available to be read from the stream. The stream must be managed by a DOS
handler that supports the ACTION_STACK packet.
See Also:QueueF()
StcToken()-break out the next token from a string
Usage:(quote,length,scan,token)=StcToken(string)
D0 D1 A0 A1 A0
Scans a null-terminated string to select the next token delimited by "white
space,"and returns a pointer to the start of the token. The quote return will
be an ASCII single or double quote if the token was quoted and 0 otherwise;
white space characters are ignored within quoted strings. The length return is
the total length of the token,including any quote characters. The scan return
is advanced beyond the current token to prepare for the next call.
StrcpyA()-copy a string,converting to ASCII
Usage:hash=StrcpyA(destination,source,length)
D0 A0 A1 D0
Copies the source string to the destination area,converting the characters to
ASCII by clearing the high-order bit of each byte. The length of the string
(which may include embedded nulls)is considered as a 2-byte usingned integer.
So the string is limited in length to 65,535 bytes. The hash return is the
internal hash byte for the copied string.
See Also:StrcpyN(),StrcpyU
StrcpyN()-copy a string
Usage:hash=StrcpyN(destination,source,length)
D0 A0 A1 D0
Copies the source string to the destination area. The length of the string
(which may include embedded nulls)is considered as a 2-byte unsigned integer.
The hash return is the internal hash byte for the copied string.
See Also:StrcpyA(),StrcpyU
StrcpyU()-copy a string,converting to uppercase
Usage:hash=StrcpyU(destination,source,length)
D0 A0 A1 D0
Copies the source string to the destination area,converting to uppercase
alphabetics. The length of the string(which may include embedded nulls)is
considered as a 2-byte unsigned integer. The has return is the internal hash
byte for the copied string.
See Also:StrcpyA(),StrcpyN
124
StrflipN()-reverse the characters in a string
Usage:StrflipN(string,length)
A0 D0
Reverses the sequence of characters in a string. The conversion is performed in
place.
Strlen()-find the length of a null-terminated string
Usage:length=Strlen(string)
D0 A0
(CCR)
Returns the number of characters in a null-terminated string. Register A0 is
preserved,and the CCR is set for the returned length.
StrcmpN()-compare the values of strings
Usage:test=StrcmpN(string1,string2,length)
D0 A0 A1 D0
(CCR)
The string1 and string2 arguments are compared for the specified number of
characters. The comparison proceeds character-by-character until a difference
is found or the maximum number of characters have been examined. The returned
value is -1 if the first string was less,1 if the first string was greater,and
0 if the strings match exactly. The CCR register is set for the returned value.
ToUpper()-translate an ASCII character to uppercase
Usage:upper=ToUpper(character)
D0 D0
Converts an ASCII character to uppercase. Only register D0 is affected.
UnlockRexxBase()-unlock a shared resource.
Usage:UnlockRexxBase(resource)
D0
Releases the specified resource,or all resources if the argument is zero. Every
call to LockRexxBase()should be followed eventually by a call to UnlockRexxBase
()for the same resource.
See Also:LockRexxBaseF()
WriteF()-write characters to a file buffer
Usage:count=WriteF(IoBuff,buffer,length)
D0 A0 A1 D0
(CCR)
Writes a buffer of characters of the specified length to the file associated
with the IoBuff pointer. The buffer argument is a pointer to a storage area,
125
and the length argument specifies the number of characters to be written. The
returned value is the actual number of characters written or -1 if an error
occurred.
See Also:CloseF(),OpenF(),ReadF()
126
APPENDIX D THE AREXX SUPPORT LIBRARY
The ARexx language system is distributed with an external function library that
provides a number of Amiga-specific functions. It is a standard Amiga shared
library named rexxsupport.library and should reside in the system
LIBS:directory. Unlike the Systems Library described in the previous
Appendix,the support library functions are callable from with ARexx programs.
The support library was designed to supplement the generic Built-In functions
with functions specific to the Amiga. This library will be expanded in future
releases,and users are encouraged to submit suggestions for additional
functions.
The Support Library must be added to the global Library List before it can be
accessed by ARexx programs. This can be done using the Built-In function
ADDLIB() or by direct communication with the resident process. The library name
must be specified as rexxsupport.library,the query function offset is -30,and
the version number is 0. The search priority can be set to 0 or whatever value
is appropriate.
ALLOCMEM()
Usage:ALLOCMEM(length,[attribute])
Allocates a block of memory of the specified length from the system free-
memory pool and returns its address as a 4-byte string. The optional attribute
parameter must be a standard EXEC memory allocation flag,supplied as a 4-byte
string. The default attribute is for "PUBLIC" memory(not cleared).
This function should be used whenever memory is allocated for use by external
programs. It is the user's responsibility to release the memory space when it
is no longer needed.
See Also:FREEMEM()
Example:
say c2x(allocmem(1000)) ==>00050000
CLOSEPORT()
Usage:CLOSEPORT(name)
Closes the message port specified by the name argument,which must have been
allocated by a call to OPENPORT()within the current ARexx program. Any messages
received but not yet REPLYed are automatically returned with the return code
set to 10.
See Also:OPENPORT()
Example:
call closeport myport
127
FREEMEM()
Usage:FREEMEM(address,length)
Releases a block of memory of the given length to the system freelist. The
address parameter is a four-byte string,typically obtained by a prior call to
ALLOCMEM(). FREEMEM()cannot be used to release memory allocated using
GETSPACE(),the ARexx internal memory allocator. The returned value is a boolean
success flag.
See Also:ALLOCMEM()
Example:
say freemem('00042000'x,32) ==>1
GETARG()
Usage:GETARG(packet,[n])
Extracts a command,function name,or argument string from a message packet. The
packet argument must be a 4-byte address obtained from a prior call to
GETPKT(). The optional n argument specifies the slot containing the string to
be extracted,and must be less than or equal to the actual argument count for
the packet. Commands and functions names are always in slot 0;function packets
may have argument strings in slots 1-15.
Examples:
command = getarg(packet)
function= getarg(packet,0) /* name string */
arg1 = getarg(packet,1) /* 1st argumeent*/
GETPKT()
Usage:GETPKT(name)
Checks the message port specified by the name argument to see whether any
messages are available. The named message port must have been opened by a prior
call to OPENPORT() within the current ARexx program. The returned value is the
4-byte address of the first message packet,or '0000 0000'x if no packets were
available.
The function returns immediately whether or not a packet is enqueued at the
message port. Programs should never be designed to "busy-loop" on a message
port. If there is no useful work to be done until the next message packet
arrives,the program should call WAITPKT()and allow other tasks to proceed.
See Also:WAITPKT()
Example:
packet = getpkt('MyPort')
OPENPORT()
Usage:OPENPORT(name)
Creates a public message port with the given name. The returned value is the
4-byte address of the Port Resource strcture or '0000 000'xif the port could
not be opened or initialized. An initialization failure will occur if another
port of the same name already exists,or if a signal bit couldn't be allocated.
128
The message port is allocated as a Port Resource node and is linked into the
program's global data structure. Ports are automatically closed when the
program exits,and any pending messages are returned to the sender.
See Also:CLOSEPORT()
Example:
myport = openport("MyPort")
REPLY()
Usage:REPLY(packet,rc)
Returns a message packet to the sender,with the primary result field set to the
value given by the rc argument. The secondary result is cleared. The packet
argument must be supplied as a 4-byte address,and the rc argument must be a
whole number.
Example:
call reply packet,10 /* error return*/
SHOWDIR()
Usage:SHOWDIR(directory,['All' | 'File' | 'Dir'])
Returns the contents of the specified directory as a string of names separated
by blanks. The second parameter is an option keyword that selects whether all
entries,only files,or only subdirectories will be included.
Example:
say showdir("df1:c") ==>rx ts te hi tco tcc
SHOWLIST()
Usage:SHOWLIST[{'D' | 'L' | 'P' | 'R' | 'W' },[name])
The first argument is an option keyword to select a system list;the options
currently supported are Devices,Libraries,Ports,Ready,and Waiting. If only the
first parameter is supplied,the function scans the selected list and returns
the node names in a string separated by blanks. If the name parameter is
supplied,the boolean return indicates whether the specified list contains a
node of that name. The name matching is case-sensitive.
The list is scanned with task switching forbidden so as to provide an accurate
snapshot of the list at that time.
Example:
say showlist('P') ==>REXX MyCon
say showlist('P','REXX') ==>1
129
STATEF()
Usage:STATEF(filename)
Returns a string containing information about an external file. The string is
formatted as "{DIR | FILE} length blocks protection comment."
The length token gives the file length in bytes,and the block token specifies
the file length in blocks.
Example:
say statef("libs:rexxsupport.library")
/* would give "FILE 1880 4 RWED " */
WAITPKT()
Usage:WAITPKT(name)
Waits for a message to be received at the specified(named)port,which must have
been opened by a call to OPENPORT() within the current ARexx program. The
returned boolean value indicates whether a message packet is available at the
port. Normally the returned value will be 1(True),since the function waits
until an event occurs at the message port.
The packet must then be removed by a call to GETPKT(),and should be returned
eventually using the REPLY()function. Any message packets received but not
returned when an ARexx program exits are automatically REPLYed with the return
code set to 10.
Example:
call waitpkt 'MyPort' /* wait awhile */
130
APPENDIX E DISTRIBUTION FILES
This appendix lists the directores of the standard ARexx distribution disk. The
contents of some of the directories may change from time to time,so your disk
may not show exactly the same files. Most notably,the :rexx directory will
expand as more program examples are included in it.
The second section of the Appendix lists the HEADER files that define the
constants and data structures used with ARexx. All of these files are available
in the :INCLUDE directory,but are listed here for convenience in studying the
structures.
E-1 DIRECTORIES
The files are listed below as they would be using the system dir command. For
example,"dir df1:c opt a" would list the contents of the :c directory on disk
drive 1.
THE :C DIRECTORY
This directory contains the command utilities used with ARexx. These files
should be copied to your system C: directory when you install the program.
c(dir)
hi loadlib
rexxmast rx
rxc rxset
tcc tco
te ts
THE :INCLUDE DIRECTORY
This directory has the INCLUDE and HEADER files used for assembly language and
"C" programming,respectively. These files contain the structure definitions
necessary to build an interface to ARexx.
include(dir)
errors.h rexxio.h
rxslib.h storage.h
errors.i rexxio.i
rxslib.i storage.i
131
THE :LIBS DIRECTORY
These are the library files for the language interpreter and the Support
Library functions. Both files should be copied to your system LIBS:directory
when you install ARexx.
libs(dir)
rexxsupport.library rexxsyslib.library
THE :REXX DIRECTORY
The :rexx directory contains example programs to illustrate various features of
the language. New files will be added from time to time,and users are welcome
to contribute files to be distributed in this way.
rexx(dir)
bigif.rexx break.rexx
builtin.rexx calc.rexx
cmdtest.rexx fact.rexx
factw.rexx haltme.rexx
hosttest.rexx iftest.rexx
marquis.rexx nesttest.rexx
paver.rexx potpourii.rexx
rslib.rexx select.rexx
sigtest.rexx support.rexx
test1.rexx timer.rexx
THE :TOOLS DIRECTORY
These files are intended for software developers,and include examples of
interfacing to ARexx. The file rexxtest is of particular interest;it calls the
ARexx interpreter directly,and can be run under a debugger to aid with
developing new function libraries.
tools(dir)
hosttest hosttest.asm
loadlib.asm rexxtest
rexxtest.asm rxoffsets.o
Miscellaneous Files
.info Install-ARexx
README Start-Aexx
132
E-2 LISTINGS OF HEADER FILES
This section of the chapter consists of listings of the header files contained
in the :include directory.
storage.h
This is the main header file and contains definitions for all of the important
data structures used by ARexx.
/*===rexx/storage.h=================================================
*
* Copyright (c) 1986,1987 by William S. Hawes (All Rights Reserved)
*
*==================================================================
* Header file to define ARexx data structures.
*/
#ifndef REXX_STORAGE_H
#define REXX_STORAGE_H
#ifndef EXEC_TYPES_H
#include "exec/types.h"
#endif
#ifndef EXEC_NODES_H
#include "exec/nodes.h"
#endif
#ifndef EXEC_LISTS_H
#include "exec/lists.h"
#endif
#ifndef EXEC_PORTS_H
#include "exec/ports.h"
#endif
#ifndef EXEC_LIBRARIES_H
#include "exec/libraries.h"
#endif
/* The NexxStr structue is used to maintain the internal strings in REXX.
* It includes the buffer area for the string and associated attributes.
* This is actually a variable-length structure;it is allocated for a
* specific length string,and the length is never modified thereafter
* (since it's used for recycling).
*/
133
storage.h(cont.)
struct NexxStr{
LONG ns_Ivalue; /* integer value */
UWORD ns_Length; /* length in bytes(excl null) */
UBYTE ns_Flags; /* attribute flags */
UBYTE ns_Hash; /* hash code */
BYTE ns_Buff[8]; /* buffer area for strings */
}; /* size: 16 bytes (minimum) */
#define NXADDLEN 9 /* offset plus null byte */
#define IVALUE(nsPtr) (nsPtr->ns_Ivalue)
/* String attribute flag bit definitions */
#define NSB_KEEP 0 /* permanent string? */
#define NSB_STRING 1 /* string form valid? */
#define NSB_NOTNUM 2 /* non-numeric? */
#define NSB_NUMBER 3 /* a valid number? */
#define NSB_BINARY 4 /* integer value saved? */
#define NSB_FLOAT 5 /* floating point format? */
#define NSB_EXT 6 /* an external string? */
#define NSB_SOURCE 7 /* part of the program source? */
/* The flag form of the string attributes */
#define NSF_KEEP (1<< NSB_KEEP ) */
#define NSF_STRING (1<< NSB_STRING)
#define NSF_NOTNUM (1<< NSB_NOTNUM)
#define NSF_NUMBER (1<< NSB_NUMBER)
#define NSF_BINARY (1<< NSB_BINARY)
#define NSF_FLOAT (1<< NSB_FLOAT )
#define NSF_EXT (1<< NSB_EXT )
#define NSF_SOURCE (1<< NSB_SOURCE)
* Combinations of flags
#define NSF_INTNUM (NSF_NUMBER | NSF_BINARY | NSF_STRING)
#define NSF_DPNUM (NSF_NUMBER | NSF_FLOAT)
#define NSF_ALPHA (NSF_NOTNUM | NSF_STRING)
#define NSF_OWNED (NSF_SOURCE | NSF_EXT | NSF_KEEP
#define KEEPSTR (NSF_STRING | NSF_SOURCE | NSF_NOTNUM)
#define KEEPNUM (NSF_STRING | NSF_SOURCE | NSF_NUMBER | NSF_BINARY)
134
storage.h (cont.)
/* The RexxArg structure is identical to the NexxStr structure,but
* is allocated from system memory rather than from internal storage.
* This structure is used for passing arguments to external programs.
* It is usually passed as an "argstring",a pointer to the string buffer.
*/
struct RexxArg {
LONG ra_Size; /* total allocated length */
UWORD ra_Length; /* length of string */
UBYTE ra_Flags; /* attribute flags */
UBYTE ra_Hash; /* hash code */
BYTE ra_Buff[8]; /* buffer area */
}; /* size: 16 bytes (minimum) */
/* The RexxMsg structure is used for all communications with Rexx programs.
* It is an EXEC message with a parameter block appended.
*/
struct RexxMsg{
struct Message rm_Node; /* EXEC message structure */
APTR rm_TaskBlock; /* pointer to global structure */
APTR rm_LibBase; /* library base */
LONG rm_Action; /* command (action) code */
LONG rm_Result1; /* primary result (return code) */
LONG rm_Result2; /* secondary result */
STRPTR rm_Args[16]; /* argument block(ARGO-ARG15) */
struct MsgPort *rm_PassPort; /* forwarding port */
STRPTR rm_CommAddr; /* host address (port name) */
STRPTR rm_FileExt; /* file extension */
LONG rm_Stdin; /* input stream(filehandle) */
LONG rm_Stdout; /* output steam(filehandle) */
LONG rm_avail; /* future expension */
}; /* size: 128 bytes */
/* Field definitions
#define ARGO(rmp) (rmp->rm_Args[0] /* start of argblock */
#define ARG1(rmp) (rmp->rm_Args[1] /* first argument */
#define ARG2(rmp) (rmp->rm_Args[2] /* second argument */
#define MAXRMARG 15 /* maximum arguments */
/* Command (action) codes for message packets */
#define RXCOMM $01000000 /* a command-level invocation */
#define RXFUNC $02000000 /* a function call */
#define RXCLOSE $03000000 /* close the port */
#define RXQUERY $04000000 /* query for information */
#define RXADDFH $07000000 /* add a function host */
135
storage.h (cont.)
#define RXADDLIB $08000000 /* add a function library */
#define RXREMLIB $09000000 /* remove a function library */
#define RXADDCON $0A000000 /* add/update a ClipList string */
#define RXREMCON $0B000000 /* remove a ClipList string */
#define RXTCOPN $0C000000 /* open the trace console */
#define RXTCCLS $0D000000 /* close the trace console */
/* Command modifier flag bits */
#define RXFB_NOIO 16 /* suppress I/O inheritance? */
#define RXFB_RESULT 17 /* result string expected? */
#define RXFB_STRING 18 /* program is a "string file"? */
#define RXFB_TOKEN 19 /* tokenize the command line? */
#define RXFB_NONRET 20 /* a "no-return" message? */
/* Modifier flags */
#define RXFF_RESULT (1<< RSFB_RESULT)
#define RXFF_STRING (1<< RXFB_STRING)
#define RXFF_TOKEN (1<< RXFB_TOKEN )
#define RXFF_NONRET (1<< RXFB_NONRET)
#define RXCODEMASK $FF000000
#define RXARGMASK $0000000F
/* The RexxRsrc structure is used to manage global resources.
* The name string for each node is created as a RexxArg structure,
* and the total size of the node is saved in the "rr_Size" field.
* Functions are provided to allocate and release resource nodes.
* If special deletion operations are required,an offset and base can
* be provided in "rr_Func" and "rr_Base",respectively. This function
* will be called with the base in register A6 and the node in A0.
*/
struct RexxRsrc {
struct Node rr_Node;
WORD rr_Func; /* a "auto-delete" offset */
APTR rr_Base; /* "auto-delete" base */
LONG rr_Size; /* total size of node */
LONG rr_Arg1; /* available ... */
LONG rr_Arg2; /* available ... */
}; /* size: 32 bytes */
/* Resource node types */
#define RRT_ANY 0 /* any node type ... */
#define RRT_LIB 1 /* a function library */
#define RRT_PORT 2 /* a public port */
#define RRT_FILE 3 /* a file IoBuff */
#define RRT_HOST 4 /* a function host */
#define RRT_CLIP 5 /* a Clip List node */
136
storage.h (cont.)
/* The RexxTask structure holds the fields used by REXX to communicate with
* external processes,including the client task. It includes the global
* data structure(and the base environment). The structure is passed to
* the newly-created task in its "wake-up" message.
*/
#define GLOBALSZ 200 /* total size of GlobalData */
struct RexxTask {
BYTE rt_Global[GLOBALSZ]; /* global data structure */
struct MsgPort rt_MsgPort; /* global message port */
UBYTE rt_Flags; /* task flag bits */
BYTE rt_SigBit; /* signal bit */
APTR rt_ClientID; /* the client's task ID
APTR rt_MsgPkt; /* the packet being processed
APTR rt_TaskID; /* our task ID
APTR rt_RexxPort; /* the REXX public port
APTR rt_ErrTrap; /* Error trap address
APTR rt_StackPtr; /* stack pointer for traps
struct List rt_Header1; /* Environment list */
struct List rt_Header2; /* Memory freelist */
struct List rt_Header3; /* Memory allocation list */
struct List rt_Header4; /* Files list */
struct List rt_Header5; /* Message Ports List */
};
/* Definitions for RexxTask flag bits
#define RTFB_TRACE 0 /* external trace flag */
#define RTFB_HALT 1 /* external halt flag */
#define RTFB_SUSP 2 /* suspend task? */
#define RTFB_TCUSE 3 /* trace console in use? */
#define RTFB_WAIT 6 /* waiting for reply? */
#define RTFB_CLOSE 7 /* task completed? */
/* Definitions for memory allocation constants */
#define MEMQUANT 16 /* quantum of memory space */
#define MEMMASK $FFFFFFF0 /* mask for rounding the size */
#define MEMQUICK (1 << 0 ) /* EXEC flags: MEMF_PUBLIC */
#define MEMCLEAR (1 << 16) /* EXEC flags: MEMF_CLEAR */
137
storage.h (cont.)
/* The SrcNode is a temporary structure used to hold values destined for a
* segment array. It is also used to maintain the memory freelist.
*/
struct SrcNode {
struct SrcNode *sn_Succ; /* next node */
struct SrcNode *sn_Pred;
APTR sn_Ptr; /* pointer value */
LONG sn_Size; /* size of object */
}; /* size: 16 bytes */
#endif
138
rxslip.h
This file defines the library base for the ARexx Systems Library.
/* === rexx/rxslib.h========================================================
*
* Copyright (c) 1986,1987 by William S. Hawes (All Rights Reserved)
*
*===========================================================================
* The header file for the REXX Systems Library
*/
#ifndef REXX_RXSLIB_H
#define REXX_RXSLIB_H
#ifndef REXX_STORAGE_H
#include "rexx/storage.h"
#endif
/* Some macro definitions */
#define RXSNAME "rexxsyslib.library"
#define RXSID "rexxsyslib 1.0 (23 AUG 87)"
#define RXSDIR "REXX"
#define RXSTNAME "ARexx"
/* The REXX systems library structure. This should be considered */
/* semi-private and read-only,except for documented exceptions */
struct RxsLib {
struct Library rl_Node; /* EXEC library node */
UBYTE rl_Flags; /* global flags */
UBYTE rl_pad;
APTR rl_SysBase; /* EXEC library base */
APTR rl_DOSBase; /* DOS library base */
APTR rl_IeeeDPBase; /* IEEE DP match library base */
LONG rl_SegList; /* library seglist */
LONG rl_MaxAlloc; /* maximum expression allocation*/
LONG rl_Chunk; /* allocation quantum */
LONG rl_MaxNest; /* maximum expression nesting */
struct NexxStr *rl_NULL; /* static string: NULL */
struct NexxStr *rl_FALSE; /* static string: FALSE */
struct NexxStr *rl_TRUE; /* static string: TRUE */
struct NexxStr *rl_REXX; /* static string: REXX */
struct NexxStr *rl_COMMAND; /* static string: COMMAND
struct NexxStr *rl_STDIN; /* static string: STDIN
struct NexxStr *rl_STDOUT; /* static string: STDOUT
struct NexxStr *rl_STDERR; /* static string: STDERR
139
rxslib.h (cont.)
STRPTR rl_Version; /* version/configuration string */
STRPTR rl_TaskName; /* name string for tasks */
LONG rl_TaskPri; /* starting prioity */
LONG rl_TaskSeg; /* startup seglist */
LONG rl_StackSize; /* stack size */
STRPTR rl_RexxDir; /* REXX directory */
STRPTR rl_CTABLE; /* character attribute table */
struct NexxStr *rl_Notice; /* copyright notice */
struct MsgPort rl_RexxPort; /* REXX public port */
UWORD rl_ReadLock; /* lock count */
LONG rl_TraceFH; /* global trace console */
struct List rl_TaskList; /* REXX task list */
WORD rl_NumTask; /* task count */
struct List rl_TaskList; /* Library List header */
WORD rl_NumLib; /* library count */
struct List rl_ClipList; /* ClipList header */
WORD rl_NumClip; /* clip node count */
struct List rl_MsgList; /* pending messages */
WORD rl_NumMsg; /* pending count */
};
/* Global flag bit definitions for RexxMaster */
#define RLFB_TRACE RTFB_TRACE /* interactive tracing? */
#define RLFB_HALT RTFB_HALT /* halt execution? */
#define RLFB_SUSP RTFB_SUSP /* suspend execution? */
#define RLFB_TCUSE RTFB_TCUSE /* trace console in use? */
#define RLFB_TCOPN 4 /* trace console open? */
#define RLFB_STOP 6 /* deny further invocations */
#define RLFB_CLOSE 7 /* close the master */
#define RLFMASK 0x07 /* passed flags */
; Initialization constants
#define RXSVERS 2 /* main version */
#define RXSREV 1 /* revision */
#define RXSALLOC 0x800000 /* maximum allocation */
#define RXSCHUNK 1024 /* allocation quantum */
#define RXSNEST 32 /* expression nesting limit */
#define RXSTPRI 0 /* task priority */
#define RXSSTACK 4096 /* stack size */
#define RXSLISTH 4 /* number of list headers */
140
rxslib.h (cont.)
/* Character attribute flag bits used in REXX. Defined only for */
/* ASCII characters (range 0-127) */
#define CTB_SPACE 0 /* white space characters */
#define CTB_DIGIT 1 /* decimal digits 0-9 */
#define CTB_ALPHA 2 /* alphabetic characters */
#define CTB_REXXSYM 3 /* REXX symbol characters */
#define CTB_REXXOPR 4 /* REXX operator characters */
#define CTB_REXXSPC 5 /* REXX special symbols */
#define CTB_UPPER 6 /* UPPERCASE alphabetic */
#define CTB_LOWER 7 /* lowercase alphabetic */
/* Attribute flags */
#define CTF_SPACE (1 << CTB_SPACE)
#define CTF_DIGIT (1 << CTB_DIGIT)
#define CTF_ALPHA (1 << CTB_ALPHA)
#define CTF_REXXASYM (1 << CTB_REXXSYM)
#define CTF_REXXOPR (1 << CTB_REXXOPR)
#define CTF_REXXSPC (1 << CTB_REXXSPC)
#define CTF_UPPER (1 << CTB_UPPER)
#define CTF_LOWER (1 << CTB_LOWER)
#endif
141
rexxio.h
This file defines the data structures used for buffered I/O. ARexx uses linked
lists of IoBuff structures to keep track of the files it opens. Each IoBuff
node is allocated as an "auto-delete" structure and can be closed and released
by a call to either CloseF() or RemRsrcNode(). An entire list of files can be
closed with a call to RemRsrcList().
/* ===rexx/rexxio.h========================================================
*
* Copyright (c) 1986,1987 by William S. Hawes (All Rights Reserved)
*
*=========================================================================
* Header file for ARexx Input/Output related structures
*/
#ifndef REXX_REXXIO_H
#define REXX_REXXIO_H
#ifndef REXX_STORAGE_H
#include "rexx/storage.h"
#endif
#define RXBUFFSZ 204 /* buffeg length */
/* The IoBuff is a resource node used to maintain the File List. Nodes are
* allocated and linked into the list whenever a file is opened.
*/
struct IoBuff{
struct RexxRsrc iobNode; /* structure for files/strings */
APTR iobRpt; /* read/write pointer */
LONG iobRct; /* character count */
LONG iobDFH; /* DOS filehandle */
APTR iobLock; /* DOS lock */
LONG iobBct; /* buffer length */
BYTE iobArea[RXBUFFSZ]; /* buffer area */
}; /* size: 256 bytes */
/* Access mode definitions */
#define RXIO_EXIST -1 /* an external filehandle */
#define RXIO_STRF 0 /* a "string file" */
#define RXIO_READ 1 /* read-only access */
#define RXIO_WRITE 2 /* write mode */
#define RXIO_APPEND 3 /* append mode (existing file) */
142
rxxio.h (cont.)
/* Offset anchors for SeekF() */
#define RXIO_BEGIN -1 /* relative to start */
#define RXIO_CURR 0 /* relative to current position */
#define RXIO_END 1 /* relative to end */
/* The Library List contains just plain resource nodes */
#define LLOFFSET(rrp) (rrp>rr_Arg1) /* "Query" offset */
#define LLVERS(rrp) (rrp->Arg2) /* library version */
/* The RexxClipNode structure is used to maintain the Clip List. The
* The ReplyList holds packets that have been received but haven't been
* replied.
*/
struct RexxMsgPort{
struct RexxRsrc rmp_Node; /* linkage node */
struct MsgPort rmp_Port; /* the message port */
struct List rmp_ReplyList; /* messages awaiting reply */
};
/* DOS Device types */
#define DT_DEV 0 /* a device */
#define DT_DIR 1 /* an ASSIGNed directory */
#define DT_VOL 2 /* a volume */
/* Private DOS packet types */
#define ACTION_STACK 2002 /* stack a line */
#define ACTION_QUEUE 2003 /* queue a line */
#endif
143
errors. h
This file contains the definitions for all of the error messages issued by the
ARexx interpreter.
/* == errors.h================================================================
*
* Copyright (c) 1987 by Williams S. Hawes (All Rights Reserved)
*
* ===========================================================================
* Definitions for ARexx error codes
*/
#define EERC_MSG 0 /* error code offset */
#define ERR10_001 (ERRC_MSG+1) /* program not found */
#define ERR10_002 (ERRC_MSG+2) /* execution halted */
#define ERR10_003 (ERRC_MSG+3) /* no memory available */
#define ERR10_004 (ERRC_MSG+4) /* invalid character in program */
#define ERR10_005 (ERRC_MSG+5) /* unmatched quote */
#define ERR10_006 (ERRC_MSG+6) /* unterminated comment */
#define ERR10_007 (ERRC_MSG+7) /* clause too long */
#define ERR10_008 (ERRC_MSG+8) /* unrecognized token */
#define ERR10_009 (ERRC_MSG+9) /* symbol or string too long */
#define ERR10_010 (ERRC_MSG+10) /* invalid message packet */
#define ERR10_011 (ERRC_MSG+11) /* command string error */
#define ERR10_012 (ERRC_MSG+12) /* error return from function */
#define ERR10_013 (ERRC_MSG+13) /* host environment not found */
#define ERR10_014 (ERRC_MSG+14) /* required library not found */
#define ERR10_015 (ERRC_MSG+15) /* function not found */
#define ERR10_016 (ERRC_MSG+16) /* no return value */
#define ERR10_017 (ERRC_MSG+17) /* wrong number of arguments */
#define ERR10_018 (ERRC_MSG+18) /* invalid argument to function */
#define ERR10_019 (ERRC_MSG+19) /* invalid PROCEDURE */
#define ERR10_020 (ERRC_MSG+20) /* unexpected THEN/ELSE */
#define ERR10_021 (ERRC_MSG+21) /* unexpected WHEN/OTHERWISE */
#define ERR10_022 (ERRC_MSG+22) /* unexpected LEAVE or ITERATE */
#define ERR10_023 (ERRC_MSG+23) /* invalid statement in SELECT */
#define ERR10_024 (ERRC_MSG+24) /* missing THEN clauses */
#define ERR10_025 (ERRC_MSG+25) /* missing OTHERWISE */
#define ERR10_026 (ERRC_MSG+26) /* missing or unexpected END */
#define ERR10_027 (ERRC_MSG+27) /* symbol mismatch on END */
#define ERR10_028 (ERRC_MSG+28) /* invalid DO syntax */
#define ERR10_029 (ERRC_MSG+29) /* incomplete DO/IF/SELECT */
144
errors.h (cont.)
#define ERR10_030 (ERRC_MSG+30) /* label not found */
#define ERR10_031 (ERRC_MSG+31) /* symbol expected */
#define ERR10_032 (ERRC_MSG+32) /* string or symbol expected */
#define ERR10_033 (ERRC_MSG+33) /* invalid sub-keyword */
#define ERR10_034 (ERRC_MSG+34) /* required keyword missing */
#define ERR10_035 (ERRC_MSG+35) /* extraneous characters */
#define ERR10_036 (ERRC_MSG+36) /* sub-keyword conflict */
#define ERR10_037 (ERRC_MSG+37) /* invalid template */
#define ERR10_038 (ERRC_MSG+38) /* invalid TRACE request */
#define ERR10_039 (ERRC_MSG+39) /* uninitialized variable */
#define ERR10_040 (ERRC_MSG+40) /* invalid variable name */
#define ERR10_041 (ERRC_MSG+41) /* invalid expression */
#define ERR10_042 (ERRC_MSG+42) /* unbalanced parentheses */
#define ERR10_043 (ERRC_MSG+43) /* nesting level exceeded */
#define ERR10_044 (ERRC_MSG+44) /* invalid expression result */
#define ERR10_045 (ERRC_MSG+45) /* expression required */
#define ERR10_046 (ERRC_MSG+46) /* boolean value not 0 or 1 */
#define ERR10_047 (ERRC_MSG+47) /* arithmetic conversion error */
#define ERR10_048 (ERRC_MSG+48) /* invalid operand */
/* Return Codes for general use ... */
#define RC_FAIL -1 /* something's wrong */
#define RC_OK 0 /* success */
#define RC_WARN 5 /* warning only */
#define RC_ERROR 10 /* something's wrong */
#define RC_FATAL 20 /* complete or severe failure */
145
GLOSSARY
ALLOCATION. A grant of a system resource,such as memory space. Programs
designed to run in a multitasking environment generally use dynamic allocation
to avoid tying up system resources.
AMIGADOS. The higher-level part of the Amiga operating system that supports the
filing system and input/output operations.
ARGSTRING. An "argument string" structure used to pass data to an ARexx
program. The structure is passed as a pointer to the buffer area containing the
string data,and can be treated as a pointer to a null-terminated string.
ARGUMENT. A data item passed to a function,sometimes called a parameter.
CLAUSE. A group of one or more tokens forming a "sentence" in a language. The
clause is the smallest executable language fragment.
COMMAND LINE INTERFACE (CLI). A program that accepts input from the user and
runs programs based on the entered command. The CLI generally refers to the
command interpreter supplied with the Amiga,but other command "shells" may be
used instead.
CONCATENATION. An operation in which two strings are joined or "chained
together." ARexx provides two concatenation operators,one of which joins
strings directly and the other of which embeds a blank between the operands.
EXEC. The multitasking kernel of the Amiga's operating system. EXEC provides
the task scheduling,interrupt handlin,and message-passing primitives used to
support ARexx.
FUNCTION HOST. A program that manages a public message port for receiving
function invocation messages. The message port may be the same one used for
command messages.
FUNCTION LIBRARY. A collection of functions callable from ARexx and managed as
an Amiga shared library. Each function library includes an entry point to
associate a function name with the code to be called.
HOST ADDRESS. The name of the public message port associated with a host
application. The host address is used as the unique identifier for the host,and
should be unique within the system message ports list. Within an ARexx program
the host address identifies the external host to which commands will be sent.
147
HOST APPLICATION. An executable program that program that provides a suitable
command interface to receive ARexx commands. Most host applications will also
provide a means to invoke macro programs from within the application.
INTERRUPT. An event that alters the normal flow of control in a program.
Interrupts in ARexx refer to events within the program execution and are
distinct from the hardware-level interrupts managed by the Amiga EXEC system.
MACRO PROGRAM. A program that implements a complex "macro" operation from a
series of "micro" commands.
MESSAGE PACKET. A data structure used to pass information between tasks. A
message packet is allocated and initialized by one task and then sent to
another task's message port. After the recipient has processed the message,it
"replies" the message to the replyport associated with the message.
MESSAGE PORT. A data structure used as the rendezvous point for message
passing. A message port provides the anchor for a list of message packets and
identifies the task to be signalled when a message arrives.
MULTITASKING. The ability to run more than one program at a time. More
precisely, multitasking permits the resources of the computer to be shared
among many tasks without forcing any task to be aware of the others.
PROCESS. An extension to an EXEC task structure that provides the data fields
required to use AmigaDOS functions. All ARexx programs run as AmigaDOS
processes.
REPLYPORT. A message port designated to receive a returning message packet.
Each message packet includes a field that specifies its reply port.
RESIDENT PROCESS. The program responsible for launching ARexx programs and for
managing various resources used by ARexx. It is structured as a host
application and opens a public message port named "REXX."
SHARED LIBRARY. A collection of executable code and data managed as a resource
by the EXEC operating system. As the name "shared" implies, the code and data
in a library can be used by more than one task.
STORAGE ENVIRONMENT. The collection of data values forming the current state
of an ARexx program. Storage environments are strictly nested and only one
environment is current at any time.
TASK. An entity consisting of executable code and a data structure managed by
the EXEC operating system. The task is the smallest program unit that can be
scheduled and run separately.
148
TOKEN. The elementary words or atoms of a language. A token can be considered
as a string of one or more characters forming the smallest unit of the
language.
TYPELESS. Data items having no assumed structure or usage. ARexx treats all
data as typeless character strings and checks for specific characteristics only
when required by an operation.
149
AREXX DOCS BROUGHT TO USE BY THE SOUTHERN STAR WILL ASSISTANCE BY RAP.....
end.